<?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;

use Magento\Mray\CodeStructuralElement\Php\Reflection\ClassLikeDeclaration;
use Magento\Mray\CodeStructuralElement\FullQualifiedStructuralElementName;

class Class_ implements ClassLike
{
    /**
     * @var object
     */
    private $cl;
    /**
     * @var array
     */
    private $attributes;

    /**
     * @param ClassLikeDeclaration\Class_ $cl
     * @param array $attributes
     */
    public function __construct(ClassLikeDeclaration\Class_ $cl, array $attributes = [])
    {
        $this->cl = (object)[
            'namespacedName' => $cl->getName(),
            'extends' => $cl->getParentClass(),
            'implements' => $cl->getImplementedInterfaces(),
            'checksum' => $cl->getImplementationChecksum(),
        ];
        $this->attributes = $attributes;
    }

    /**
     * @return FullQualifiedStructuralElementName|null
     */
    public function getFqsen(): ?FullQualifiedStructuralElementName
    {
        if (isset($this->cl->namespacedName)) {
            return new PhpFqsen\ClassLike((string)$this->cl->namespacedName);
        }
        return null;
    }

    /**
     * @return PhpFqsen\ClassLike|null
     */
    public function getParentClassFqsen(): ?PhpFqsen\ClassLike
    {

        if (isset($this->cl->extends)) {
            return new PhpFqsen\ClassLike((string)$this->cl->extends);
        }
        return null;
    }

    /**
     * @return PhpFqsen\ClassLike[]
     */
    public function getImplementedInterfacesFqsen(): array
    {
        $fqsens = [];
        foreach ($this->cl->implements as $implements) {
            $fqsens[] = new PhpFqsen\ClassLike((string)$implements);
        }
        return $fqsens;
    }

    /**
     * @return string
     */
    public function getType(): string
    {
        return 'Php_Class';
    }

    /**
     * @param string $attr
     * @param mixed $val
     */
    public function setAttribute(string $attr, $val): void
    {
        $this->attributes[$attr] = $val;
    }

    /**
     * @param string $attr
     * @param mixed $default
     * @return mixed|null
     */
    public function getAttribute(string $attr, $default = null)
    {
        return $this->attributes[$attr] ?? $default;
    }

    /**
     * @return array
     */
    public function getAttributes(): array
    {
        return $this->attributes;
    }

    /**
     * @return string|null
     */
    public function getChecksum(): ?string
    {
        return $this->cl->checksum;
    }
}
