<?php

namespace Lc\ShopBundle\Model;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Lc\ShopBundle\Context\FilterMerchantInterface;
use Lc\ShopBundle\Context\TreeInterface;

/**
 * @ORM\MappedSuperclass()
 */
abstract class ProductCategory extends AbstractDocumentEntity implements TreeInterface, FilterMerchantInterface
{

        /**
         * @ORM\ManyToOne(targetEntity="Lc\ShopBundle\Context\MerchantInterface", inversedBy="productCategories")
         * @ORM\JoinColumn(nullable=false)
         */
        protected $merchant;

        /**
         * @ORM\ManyToOne(targetEntity="Lc\ShopBundle\Context\ProductCategoryInterface", inversedBy="childrens")
         */
        protected $parent;

        /**
         * @ORM\OneToMany(targetEntity="Lc\ShopBundle\Context\ProductCategoryInterface", mappedBy="parent" , fetch="EAGER"))
         * @ORM\OrderBy({"position" = "ASC"})
         */
        protected $childrens;

        /**
         * @ORM\ManyToMany(targetEntity="Lc\ShopBundle\Context\ProductFamilyInterface", mappedBy="productCategories")
         */
        protected $productFamilies;

        /**
         * @ORM\Column(type="boolean")
         */
        protected $saleStatus;


        /**
         * @ORM\ManyToOne(targetEntity="Lc\ShopBundle\Context\SectionInterface", inversedBy="productCategories")
         * @ORM\JoinColumn(nullable=false)
         */
        protected $section;

        public function __construct()
        {
                $this->childrens = new ArrayCollection();
                $this->productFamilies = new ArrayCollection();
        }

        public function __toString()
        {
                $parent = $this->getParent() ;
                $title = $parent ? $parent->getTitle().' - ' : '' ;
                $title .= $this->getTitle() ;
                return $title ;
        }

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

        public function setParent(?self $productCategory): self
        {
                $this->parent = $productCategory;

                return $this;
        }

        public function getParentCategory()
        {
                if($this->getParent()) {
                        return $this->getParent() ;
                }

                return $this ;
        }

        /**
         * @return Collection|self[]
         */
        public function getChildrens(): Collection
        {
                //TODO les lignes ci-dessous ne devraient pas exister, sert à résoudre le problème d'ordre dans le menu
                $iterator = $this->childrens->getIterator();
                $iterator->uasort(function ($a, $b) {
                        return ($a->getPosition() < $b->getPosition()) ? -1 : 1;
                });
                return new ArrayCollection(iterator_to_array($iterator));
        }

        public function addChildren(self $productCategory): self
        {
                if (!$this->childrens->contains($productCategory)) {
                        $this->childrens[] = $productCategory;
                        $productCategory->setParent($this);
                }

                return $this;
        }

        public function removeChildren(self $productCategory): self
        {
                if ($this->childrens->contains($productCategory)) {
                        $this->childrens->removeElement($productCategory);
                        // set the owning side to null (unless already changed)
                        if ($productCategory->getParent() === $this) {
                                $productCategory->setParent(null);
                        }
                }

                return $this;
        }

        /**
         * @return Collection|ProductFamily[]
         */
        public function getProductFamilies(): Collection
        {
                return $this->productFamilies;
        }

        public function addProductFamily(ProductFamily $productFamily): self
        {
                if (!$this->productFamilies->contains($productFamily)) {
                        $this->productFamilies[] = $productFamily;
                        $productFamily->addProductCategory($this);
                }

                return $this;
        }

        public function removeProductFamily(ProductFamily $productFamily): self
        {
                if ($this->productFamilies->contains($productFamily)) {
                        $this->productFamilies->removeElement($productFamily);
                        $productFamily->removeProductCategory($this);
                }

                return $this;
        }

        public function countProductFamilies($status = null)
        {
                $count = 0 ;

                foreach($this->getProductFamilies() as $productFamily) {
                        if($status === null || ($status !== null && $productFamily->getStatus() == $status)) {
                                $count ++ ;
                        }
                }

                return $count ;
        }

        public function getMerchant(): ?Merchant
        {
                return $this->merchant;
        }

        public function setMerchant(?Merchant $merchant): self
        {
                $this->merchant = $merchant;

                return $this;
        }

        public function getSaleStatus(): ?bool
        {
                return $this->saleStatus;
        }

        public function setSaleStatus(bool $saleStatus): self
        {
                $this->saleStatus = $saleStatus;

                return $this;
        }

        public function getSection(): ?Section
        {
                return $this->section;
        }

        public function setSection(?Section $section): self
        {
                $this->section = $section;

                return $this;
        }

}
