<?php

namespace AutoAdmin\Bundle\Menu\Entity;

use AutoAdmin\Bundle\Content\Entity\AbstractTranslatable;
use AutoAdmin\Bundle\Content\Entity\ContentReference;
use AutoAdmin\Bundle\Content\Entity\Interfaces\MenuItemInterface;
use AutoAdmin\Bundle\Content\Entity\Traits\SequencedTrait;
use AutoAdmin\Bundle\Content\Model\SequencedInterface;
use AutoAdmin\Bundle\Content\Model\TranslationInterface;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;

/**
 * @method getCurrentTranslation(): ?MenuItemTranslation
 */
#[ORM\Table(name: 'menu_item')]
#[ORM\Entity(repositoryClass: 'AutoAdmin\Bundle\Menu\Repository\MenuItemRepository')]
#[ORM\Cache(region: 'aa_menu')]
class MenuItem extends AbstractTranslatable implements SequencedInterface, MenuItemInterface
{
    use SequencedTrait;

    /**
     * Use these fields:
     * cf. $this->contentClass
     * cf. $this->contentId
     */
    const TYPE_LINK_CONTENT = 'content';

    /**
     * Use these fields:
     * cf. $this->uri
     */
    const TYPE_LINK_URL = 'link';

    /**
     * no specific fields for this type
     */
    const TYPE_TEXT = 'text';

    #[Groups(['group_ajax'])]
    protected ?TranslationInterface $currentTranslation = null;

    #[ORM\OneToOne(inversedBy: 'root', targetEntity: 'Menu', cascade: ['ALL'], orphanRemoval: true)]
    protected Menu $menu;

    /**
     * One Category has Many Categories.
     * @ Groups("group_ajax")
     */
    #[ORM\OneToMany(mappedBy: 'parent', targetEntity: 'MenuItem', cascade: ['persist', 'remove'])]
    #[ORM\OrderBy(['sequence' => 'ASC'])]
    protected Collection $children;

    /**
     * Many Categories have One Category.
     * @ Groups("group_ajax")
     */
    #[ORM\ManyToOne(targetEntity: 'MenuItem', inversedBy: 'children')]
    #[ORM\JoinColumn(name: 'parent_id', referencedColumnName: 'id')]
    protected ?MenuItem $parent = null;

    #[Groups(['group_ajax'])]
    #[ORM\Column(type: Types::BOOLEAN, options: ['default' => true])]
    protected bool $display = true;

    #[Groups(['group_ajax'])]
    #[ORM\Column(type: Types::STRING, length: 255)]
    protected string $type = self::TYPE_TEXT;

    #[Groups(['group_ajax'])]
    #[ORM\OneToOne(targetEntity: ContentReference::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
    protected ?ContentReference $contentReference = null;

    #[Groups(['group_ajax'])]
    #[ORM\Column(type: Types::STRING, length: 500, nullable: true)]
    protected ?string $uri = null;

    #[Groups(['group_ajax'])]
    #[ORM\Column(type: Types::JSON, nullable: true)]
    protected ?array $wrapperAttributes = [];

    #[Groups(['group_ajax'])]
    #[ORM\Column(type: Types::JSON, nullable: true)]
    protected ?array $linkAttributes = [];

    #[Groups(['group_ajax'])]
    #[ORM\Column(type: Types::JSON, nullable: true)]
    protected ?array $childrenAttributes = [];

    #[Groups(['group_ajax'])]
    #[ORM\Column(name: 'sequence', type: Types::INTEGER)]
    protected int $sequence = 0;

    public function __construct()
    {
        parent::__construct();
    }

    public function getMenu(): Menu
    {
        return $this->menu;
    }

    public function setMenu($menu): void
    {
        $this->menu = $menu;
    }

    /**
     * @return Collection<MenuItem>
     */
    public function getChildren(): Collection
    {
        return $this->children;
    }

    public function setChildren(Collection $children): void
    {
        $this->children = $children;
    }

    public function getParent(): ?MenuItem
    {
        return $this->parent;
    }

    public function setParent(?MenuItem $parent): void
    {
        $this->parent = $parent;
    }

    public function isDisplay(): bool
    {
        return $this->display;
    }

    public function setDisplay(bool $display): void
    {
        $this->display = $display;
    }

    public function getType(): string
    {
        return $this->type;
    }

    public function setType(string $type): void
    {
        $this->type = $type;
    }

    public function getUri(): ?string
    {
        return $this->uri;
    }

    public function setUri(?string $uri): void
    {
        $this->uri = $uri;
    }

    public function getWrapperAttributes(): ?array
    {
        return $this->wrapperAttributes;
    }

    public function setWrapperAttributes(?array $wrapperAttributes): void
    {
        $this->wrapperAttributes = $wrapperAttributes;
    }

    public function getLinkAttributes(): ?array
    {
        return $this->linkAttributes;
    }

    public function setLinkAttributes(?array $linkAttributes): void
    {
        $this->linkAttributes = $linkAttributes;
    }

    public function getChildrenAttributes(): ?array
    {
        return $this->childrenAttributes;
    }

    public function setChildrenAttributes(?array $childrenAttributes): void
    {
        $this->childrenAttributes = $childrenAttributes;
    }

    public function getContentReference(): ?ContentReference
    {
        return $this->contentReference;
    }

    public function setContentReference(?ContentReference $contentReference): void
    {
        $this->contentReference = $contentReference;
    }

    public function addChild(MenuItem $child): self
    {
        if (!$this->children->contains($child)) {
            $this->children->add($child);
            $child->setParent($this);
        }

        return $this;
    }

    public function removeChild(MenuItem $child): self
    {
        if ($this->children->removeElement($child)) {
            // set the owning side to null (unless already changed)
            if ($child->getParent() === $this) {
                $child->setParent(null);
            }
        }

        return $this;
    }
}
