<?php

namespace WordpressModels\ORM\Entity;

use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\JoinColumn;
use Doctrine\ORM\Mapping\OneToOne;
use Symfony\Component\Serializer\Annotation\Context;
use Symfony\Component\Serializer\Annotation\Groups;

/**
 * Entity mapping for the WordPress term_taxonomy table
 *
 * This entity is used to store the taxonomy of a term and its relationship with other terms.
 *
 * Serialization groups:
 * - read_term_taxonomy -- for reading term taxonomies.
 * - read_term_taxonomy_details -- for reading term taxonomies with details, like term and term relationships.
 */
#[
    ORM\Table('term_taxonomy'),
    ORM\Index(['taxonomy'], name: 'taxonomy'),
    ORM\UniqueConstraint('term_id_taxonomy', ['term_id', 'taxonomy']),
    ORM\Entity,
    ORM\Cache(usage: 'NONSTRICT_READ_WRITE', region: 'wp_term_taxonomy'),
]
class TermTaxonomy
{

    #[ORM\Id]
    #[ORM\Column(name: 'term_taxonomy_id', type: Types::BIGINT, options: ['unsigned' => true])]
    #[ORM\GeneratedValue(strategy: 'IDENTITY')]
    #[Groups(['read_term_taxonomy'])]
    private ?int $id = null;

    /**
     * TermTaxonomy and Term are very closely bound, so we create an association with 'EAGER' fetching strategy and
     * 'ALL' cascading strategy, such that they almost act like a single entity.
     * @var Term|null
     */
    #[OneToOne(inversedBy: 'termTaxonomy', targetEntity: Term::class, cascade: ['ALL'], fetch: 'EAGER'),
        JoinColumn('term_id', referencedColumnName: 'term_id')]
    #[Context(normalizationContext: ['groups' => ['read_term']])]
    #[Groups(['read_term_taxonomy_details'])]
    private ?Term $term = null;

    /**
     * @todo: MappedSuperClass??
     */
    #[ORM\Column(name: 'taxonomy', type: Types::STRING, length: 32)]
    #[Groups(['read_term_taxonomy'])]
    private string $taxonomy = '';

    #[ORM\Column(name: 'description', type: Types::TEXT, length: 65535)]
    #[Groups(['read_term_taxonomy'])]
    private string $description = '';

    #[
        ORM\ManyToOne(targetEntity: TermTaxonomy::class, inversedBy: 'children'),
        ORM\JoinColumn('parent', referencedColumnName: 'term_taxonomy_id')
    ]
    #[Groups(['read_term_taxonomy_details'])]
    private ?TermTaxonomy $parent = null;

    #[ORM\OneToMany(mappedBy: 'parent', targetEntity: TermTaxonomy::class)]
    #[Groups(['read_term_taxonomy_details'])]
    private Collection $children;

    #[ORM\Column(name: 'count', type: Types::BIGINT)]
    #[Groups(['read_term_taxonomy'])]
    private int $count = 0;

    #[ORM\OneToMany(mappedBy: 'termTaxonomy', targetEntity: TermRelationship::class)]
    #[Groups(['read_term_taxonomy_details'])]
    private Collection $termRelationships;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function setId(?int $id): TermTaxonomy
    {
        $this->id = $id;
        return $this;
    }

    public function getTerm(): ?Term
    {
        return $this->term;
    }

    public function setTerm(Term $termId): TermTaxonomy
    {
        $this->term = $termId;
        return $this;
    }

    public function getTaxonomy(): string
    {
        return $this->taxonomy;
    }

    public function setTaxonomy(string $taxonomy): TermTaxonomy
    {
        $this->taxonomy = $taxonomy;
        return $this;
    }

    public function getDescription(): string
    {
        return $this->description;
    }

    public function setDescription(string $description): TermTaxonomy
    {
        $this->description = $description;
        return $this;
    }

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

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

    public function getChildren(): Collection
    {
        return $this->children;
    }

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

    public function getCount(): int
    {
        return $this->count;
    }

    public function setCount(int $count): TermTaxonomy
    {
        $this->count = $count;
        return $this;
    }

    public function getTermRelationships(): Collection
    {
        return $this->termRelationships;
    }

    public function setTermRelationships(Collection $termRelationships): TermTaxonomy
    {
        $this->termRelationships = $termRelationships;
        return $this;
    }

}
