<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\Php;

use Override;
use Tempest\Highlight\Languages\Base\BaseLanguage;
use Tempest\Highlight\Languages\Php\Injections\PhpAttributeInstanceInjection;
use Tempest\Highlight\Languages\Php\Injections\PhpAttributePlainInjection;
use Tempest\Highlight\Languages\Php\Injections\PhpDocCommentInjection;
use Tempest\Highlight\Languages\Php\Injections\PhpFunctionParametersInjection;
use Tempest\Highlight\Languages\Php\Injections\PhpHeredocInjection;
use Tempest\Highlight\Languages\Php\Patterns\AttributeTypePattern;
use Tempest\Highlight\Languages\Php\Patterns\CastPattern;
use Tempest\Highlight\Languages\Php\Patterns\CatchTypePattern;
use Tempest\Highlight\Languages\Php\Patterns\ClassNamePattern;
use Tempest\Highlight\Languages\Php\Patterns\ClassPropertyPattern;
use Tempest\Highlight\Languages\Php\Patterns\ClassResolutionPattern;
use Tempest\Highlight\Languages\Php\Patterns\ClosureDebugPattern;
use Tempest\Highlight\Languages\Php\Patterns\CombinedKeywordPattern;
use Tempest\Highlight\Languages\Php\Patterns\ConstantNamePattern;
use Tempest\Highlight\Languages\Php\Patterns\ConstantPropertyPattern;
use Tempest\Highlight\Languages\Php\Patterns\ConstantTypesPattern;
use Tempest\Highlight\Languages\Php\Patterns\DoubleQuoteValuePattern;
use Tempest\Highlight\Languages\Php\Patterns\EnumBackedTypePattern;
use Tempest\Highlight\Languages\Php\Patterns\EnumCasePattern;
use Tempest\Highlight\Languages\Php\Patterns\ExtendsPattern;
use Tempest\Highlight\Languages\Php\Patterns\FunctionCallPattern;
use Tempest\Highlight\Languages\Php\Patterns\FunctionNamePattern;
use Tempest\Highlight\Languages\Php\Patterns\GroupedTypePattern;
use Tempest\Highlight\Languages\Php\Patterns\ImplementsPattern;
use Tempest\Highlight\Languages\Php\Patterns\InlineNamespacePattern;
use Tempest\Highlight\Languages\Php\Patterns\InstanceOfPattern;
use Tempest\Highlight\Languages\Php\Patterns\MultilineSingleDocCommentPattern;
use Tempest\Highlight\Languages\Php\Patterns\NamedArgumentPattern;
use Tempest\Highlight\Languages\Php\Patterns\NamespacePattern;
use Tempest\Highlight\Languages\Php\Patterns\NestedFunctionCallPattern;
use Tempest\Highlight\Languages\Php\Patterns\NewObjectPattern;
use Tempest\Highlight\Languages\Php\Patterns\OperatorPattern;
use Tempest\Highlight\Languages\Php\Patterns\PhpAsymmetricPropertyPattern;
use Tempest\Highlight\Languages\Php\Patterns\PhpCloseTagPattern;
use Tempest\Highlight\Languages\Php\Patterns\PhpOpenTagPattern;
use Tempest\Highlight\Languages\Php\Patterns\PropertyAccessPattern;
use Tempest\Highlight\Languages\Php\Patterns\PropertyHookGetPattern;
use Tempest\Highlight\Languages\Php\Patterns\PropertyHookSetParameterTypePattern;
use Tempest\Highlight\Languages\Php\Patterns\PropertyHookSetPattern;
use Tempest\Highlight\Languages\Php\Patterns\PropertyTypesPattern;
use Tempest\Highlight\Languages\Php\Patterns\ReturnTypePattern;
use Tempest\Highlight\Languages\Php\Patterns\ShortFunctionReferencePattern;
use Tempest\Highlight\Languages\Php\Patterns\SinglelineCommentPattern;
use Tempest\Highlight\Languages\Php\Patterns\SingleQuoteValuePattern;
use Tempest\Highlight\Languages\Php\Patterns\StaticClassCallPattern;
use Tempest\Highlight\Languages\Php\Patterns\StaticPropertyPattern;
use Tempest\Highlight\Languages\Php\Patterns\UntypedClassPropertyPattern;
use Tempest\Highlight\Languages\Php\Patterns\UseAsPattern;
use Tempest\Highlight\Languages\Php\Patterns\UseFunctionNamePattern;
use Tempest\Highlight\Languages\Php\Patterns\UseFunctionPattern;
use Tempest\Highlight\Languages\Php\Patterns\UsePattern;
use Tempest\Highlight\Languages\Php\Patterns\VariablePattern;

class PhpLanguage extends BaseLanguage
{
    private const array KEYWORDS = [
        'null', 'parent', 'true', 'false', '__halt_compiler',
        'abstract', 'and', 'as', 'break', 'callable', 'case',
        'catch', 'class', 'clone', 'const', 'continue', 'declare',
        'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty',
        'enum', 'enddeclare', 'endfor', 'endforeach', 'endif',
        'endswitch', 'endwhile', 'eval', 'exit', 'extends', 'final',
        'finally', 'fn', 'for', 'foreach', 'function', 'global',
        'goto', 'if', 'implements', 'include', 'include_once',
        'instanceof', 'insteadof', 'interface', 'isset', 'list',
        'match', 'namespace', 'new', 'or', 'print', 'private',
        'protected', 'public', 'readonly', 'require', 'require_once',
        'return', 'static', 'switch', 'throw', 'trait', 'try',
        'unset', 'use', 'while', 'xor', 'yield', 'yield from',
    ];

    public function getName(): string
    {
        return 'php';
    }

    #[Override]
    public function getInjections(): array
    {
        return [
            ...parent::getInjections(),
            new PhpHeredocInjection(),
            new PhpDocCommentInjection(),
            new PhpAttributePlainInjection(),
            new PhpAttributeInstanceInjection(),
            new PhpFunctionParametersInjection(),
        ];
    }

    #[Override]
    public function getPatterns(): array
    {
        return [
            ...parent::getPatterns(),

            new CastPattern(),

            new PhpOpenTagPattern(),
            new PhpCloseTagPattern(),
            new UseFunctionNamePattern(),
            new UseFunctionPattern(),
            new ClassNamePattern(),
            new NamedArgumentPattern(),
            new OperatorPattern('&&'),
            new OperatorPattern('\|\|'),
            new OperatorPattern('<=>'),
            new OperatorPattern('\?'),
            new FunctionNamePattern(),

            // KEYWORDS
            new PhpAsymmetricPropertyPattern(),
            new CombinedKeywordPattern(self::KEYWORDS),
            new ClassResolutionPattern(),
            new ShortFunctionReferencePattern(),
            new PropertyHookSetPattern(),
            new PropertyHookGetPattern(),
            new InlineNamespacePattern(),

            // COMMENTS
            new MultilineSingleDocCommentPattern(),
            new SinglelineCommentPattern(),

            // TYPES
            new AttributeTypePattern(),
            new ImplementsPattern(),
            new ExtendsPattern(),
            new UsePattern(),
            new NamespacePattern(),
            new PropertyTypesPattern(),
            new ConstantTypesPattern(),
            new ReturnTypePattern(),
            new StaticClassCallPattern(),
            new NewObjectPattern(),
            new InstanceOfPattern(),
            new UseAsPattern(),
            new CatchTypePattern(),
            new EnumBackedTypePattern(),
            new GroupedTypePattern(),
            new PropertyHookSetParameterTypePattern(),
            new ClosureDebugPattern(),

            // PROPERTIES
            new ClassPropertyPattern(),
            new PropertyAccessPattern(),
            new NestedFunctionCallPattern(),
            new FunctionCallPattern(),
            new ConstantPropertyPattern(),
            new ConstantNamePattern(),
            new UntypedClassPropertyPattern(),
            new EnumCasePattern(),
            new StaticPropertyPattern(),

            // VARIABLES
            new VariablePattern(),

            // VALUES
            new SingleQuoteValuePattern(),
            new DoubleQuoteValuePattern(),
        ];
    }
}
