<?php
/**
 * Copyright 2020 Adobe
 * All Rights Reserved.
 *
 * NOTICE: Adobe permits you to use, modify, and distribute this file in
 * accordance with the terms of the Adobe license agreement accompanying
 * it.
 */
declare(strict_types=1);

namespace Magento\Mray\CodeStructuralElement\Php\NodeRuntimeTypeResolver;

use Magento\Mray\CodeStructuralElement\Php\Reflection\Type\GlobalConstantType as DeferredDecisionType;
use Magento\Mray\CodeStructuralElement\Php\Reflection\TypeFactory;
use phpDocumentor\Reflection\Type;
use phpDocumentor\Reflection\Types;
use PhpParser\Node\Expr;
use TypeError;
use function get_class;
use function sprintf;
use function strtolower;

class ConstFetch implements Resolver, Contextual
{
    use Context;

    /**
     * @var string[]
     */
    private static $langConsts = [
        'true' => Types\Boolean::class,
        'false' => Types\Boolean::class,
        'null' => Types\Null_::class,
    ];

    /**
     * @param Expr $expr
     * @return Type
     */
    public function resolve(Expr $expr): Type
    {
        if (!$expr instanceof Expr\ConstFetch) {
            throw new TypeError(sprintf('%s is not applicable for %s expression.', self::class, get_class($expr)));
        }

        $c = (string)$expr->name;
        $langCT = self::$langConsts[strtolower($c)] ?? null;
        if (isset($langCT)) {
            return TypeFactory::get($langCT);
        }

        return new DeferredDecisionType(
            $this->getContext()->getGlobal()->getStructuralElementDeclarations(),
            $c
        );
    }
}
