<?php
/**
 * @author Colinet Julien
 */

namespace CpCreation\VitiCore\Cart\Model;

use CpCreation\VitiCore\Behavior\HasDisable;
use CpCreation\VitiCore\Behavior\HasTimestamp;
use CpCreation\VitiCore\Behavior\Impl\Disable;
use CpCreation\VitiCore\Behavior\Impl\Timestamp;
use CpCreation\VitiCore\Product\Model\Product;
use CpCreation\VitiCore\Product\Model\ProductPriceGroup;
use CpCreation\VitiCore\Shop\Model\ShippingCountry;
use CpCreation\VitiCore\Shop\Model\ShippingZone;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;

/**
 * Class Cart
 *
 * @ORM\Entity(repositoryClass="CpCreation\VitiCore\Cart\Repository\PromoRepository")
 * @ORM\Table(name="cart_promo")
 * @ORM\HasLifecycleCallbacks()
 */
class Promo implements HasTimestamp, HasDisable
{
    use Timestamp, Disable;

    /**
     * @ORM\Id()
     * @ORM\Column(type="uuid")
     * @ORM\GeneratedValue(strategy="NONE")
     *
     * @var UuidInterface
     */
    private $id;

    /**
     * @ORM\Column(type="string")
     * @Assert\NotBlank()
     *
     * @var string
     */
    private $title;

    /**
     * @ORM\Column(type="decimal", precision=3, scale=2, nullable=true)
     *
     * @var float | null
     */
    private $percent;

    /**
     * @ORM\Column(type="integer", nullable=true)
     *
     * @var integer | null
     */
    private $amount;

    /**
     * @ORM\Column(type="decimal", precision=3, scale=2, nullable=true)
     *
     * @var float | null
     */
    private $percentShippingCost;

    /**
     * @ORM\Column(type="datetime")
     * @Assert\NotBlank()
     *
     * @var \DateTime
     */
    private $beginAt;

    /**
     * @ORM\Column(type="datetime")
     * @Assert\NotBlank()
     *
     * @var \DateTime
     */
    private $endAt;

    /**
     * @var integer
     *
     * @ORM\Column(type="integer", options={"default" : 0})
     */
    private $count = 0;

    /** @var boolean
     *
     * @ORM\Column(type="boolean", options={"default" : 0})
     */
    private $auto;

    /** @var boolean
     *
     * @ORM\Column(type="boolean", options={"default" : 0})
     */
    private $multipleByQuantity;

    /** @var boolean
     *
     * @ORM\Column(type="boolean", options={"default" : 0})
     */
    private $includeShippingFees;

    /**
     * @var integer | null
     *
     * @ORM\Column(type="integer", nullable=true)
     */
    private $maxCount;

    /**
     * @var integer | null
     *
     * @ORM\Column(type="integer", nullable=true)
     */
    private $maxCountByCustomer;

    /**
     * @var integer | null
     *
     * @ORM\Column(type="integer", nullable=true)
     */
    private $minEquivalency;

    /**
     * @var integer | null
     *
     * @ORM\Column(type="integer", nullable=true)
     */
    private $maxEquivalency;

    /**
     * @ORM\ManyToMany(targetEntity="CpCreation\VitiCore\Product\Model\ProductPriceGroup")
     * @var Collection<ProductPriceGroup>
     */
    private $groups;

    /**
     * @ORM\ManyToMany(targetEntity="CpCreation\VitiCore\Shop\Model\ShippingZone")
     *
     * @var Collection | ShippingZone[]
     */
    private $zones;

    /**
     * @ORM\ManyToMany(targetEntity="CpCreation\VitiCore\Product\Model\Product")
     * @var Collection<Product>
     */
    private $products;

    public function __construct()
    {
        $this->id                  = Uuid::uuid4();
        $this->groups              = new ArrayCollection();
        $this->products            = new ArrayCollection();
        $this->zones  = new ArrayCollection();
        $this->disabled            = false;
        $this->auto                = false;
        $this->multipleByQuantity  = false;
        $this->includeShippingFees = false;
    }

    /**
     * @return UuidInterface
     */
    public function getId(): UuidInterface
    {
        return $this->id;
    }

    /**
     * @return string
     */
    public function getTitle(): ?string
    {
        return $this->title;
    }

    /**
     * @param string $title
     */
    public function setTitle(string $title): void
    {
        $this->title = $title;
    }

    /**
     * @return int|null
     */
    public function getAmount(): ?int
    {
        return $this->amount;
    }

    /**
     * @param int|null $amount
     */
    public function setAmount(?int $amount): void
    {
        $this->amount = $amount;
    }

    /**
     * @return float
     */
    public function getPercent(): ?float
    {
        return $this->percent;
    }

    /**
     * @param float $percent
     */
    public function setPercent(?float $percent): void
    {
        $this->percent = $percent;
    }

    /**
     * @return float|null
     */
    public function getPercentShippingCost(): ?float
    {
        return $this->percentShippingCost;
    }

    /**
     * @param float|null $percentShippingCost
     */
    public function setPercentShippingCost(?float $percentShippingCost): void
    {
        $this->percentShippingCost = $percentShippingCost;
    }

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

    /**
     * @param int $count
     */
    public function setCount(int $count): void
    {
        $this->count = $count;
    }

    /**
     * @return int
     */
    public function getMaxCount(): ?int
    {
        return $this->maxCount;
    }

    /**
     * @param int $maxCount
     */
    public function setMaxCount(?int $maxCount): void
    {
        $this->maxCount = $maxCount;
    }

    /**
     * @return int|null
     */
    public function getMaxCountByCustomer(): ?int
    {
        return $this->maxCountByCustomer;
    }

    /**
     * @param int|null $maxCountByCustomer
     */
    public function setMaxCountByCustomer(?int $maxCountByCustomer): void
    {
        $this->maxCountByCustomer = $maxCountByCustomer;
    }

    /**
     * @return bool
     */
    public function isAuto(): bool
    {
        return $this->auto;
    }

    /**
     * @param bool $auto
     */
    public function setAuto(bool $auto): void
    {
        $this->auto = $auto;
    }

    /**
     * @return bool
     */
    public function isMultipleByQuantity(): bool
    {
        return $this->multipleByQuantity;
    }

    /**
     * @param bool $multipleByQuantity
     */
    public function setMultipleByQuantity(bool $multipleByQuantity): void
    {
        $this->multipleByQuantity = $multipleByQuantity;
    }

    /**
     * @return bool
     */
    public function isIncludeShippingFees(): bool
    {
        return $this->includeShippingFees;
    }

    /**
     * @param bool $includeShippingFees
     */
    public function setIncludeShippingFees(bool $includeShippingFees): void
    {
        $this->includeShippingFees = $includeShippingFees;
    }
    
    /**
     * @return \DateTime
     */
    public function getBeginAt(): ?\DateTime
    {
        return $this->beginAt;
    }

    /**
     * @param \DateTime $beginAt
     */
    public function setBeginAt(\DateTime $beginAt = null): void
    {
        $this->beginAt = $beginAt;
    }

    /**
     * @return \DateTime
     */
    public function getEndAt(): ?\DateTime
    {
        return $this->endAt;
    }

    /**
     * @param \DateTime $endAt
     */
    public function setEndAt(\DateTime $endAt = null): void
    {
        $this->endAt = $endAt;
    }

    /**
     * @return int|null
     */
    public function getMinEquivalency(): ?int
    {
        return $this->minEquivalency;
    }

    /**
     * @param int|null $minEquivalency
     */
    public function setMinEquivalency(?int $minEquivalency): void
    {
        $this->minEquivalency = $minEquivalency;
    }

    /**
     * @return int|null
     */
    public function getMaxEquivalency(): ?int
    {
        return $this->maxEquivalency;
    }

    /**
     * @param int|null $maxEquivalency
     */
    public function setMaxEquivalency(?int $maxEquivalency): void
    {
        $this->maxEquivalency = $maxEquivalency;
    }

    /**
     * @param ProductPriceGroup $group
     * @return $this
     */
    public function addGroup(ProductPriceGroup $group)
    {
        $this->groups[] = $group;

        return $this;
    }

    /**
     * @param ProductPriceGroup $group
     */
    public function removeGroup(ProductPriceGroup $group)
    {
        $this->groups->removeElement($group);
    }

    /**
     * @return Collection<ProductPriceGroup>
     */
    public function getGroups(): Collection
    {
        return $this->groups;
    }

    /**
     * @return ShippingZone[]|Collection
     */
    public function getZones()
    {
        return $this->zones;
    }

    /**
     * @param ShippingZone $zone
     * @return $this
     */
    public function addZone(ShippingZone $zone)
    {
        if (!$this->zones->contains($zone)) {
            $this->zones[] = $zone;
        }

        return $this;
    }

    /**
     * @param ShippingZone $zone
     */
    public function removeZone(ShippingZone $zone)
    {
        if ($this->zones->contains($zone)) {
            $this->zones->removeElement($zone);
        }

    }

    /**
     * @param Product $product
     * @return $this
     */
    public function addProduct(Product $product)
    {
        $this->products[] = $product;

        return $this;
    }

    /**
     * @param Product $product
     */
    public function removeProduct(Product $product)
    {
        $this->products->removeElement($product);
    }

    /**
     * @return Collection<Product>
     */
    public function getProducts(): Collection
    {
        return $this->products;
    }

    /**
     * @param \Symfony\Component\Validator\Context\ExecutionContextInterface $context
     * @Assert\Callback()
     */
    public function validate(ExecutionContextInterface $context)
    {
        if (is_null($this->getPercent()) && is_null($this->getAmount() && is_null($this->getPercentShippingCost()))) {
            $message = 'Veuillez entrer un pourcentage de remise ou un montant de remise';
            $context->buildViolation($message)
                    ->atPath('percent')
                    ->addViolation();
        }

        if ($this->getPercent() && $this->getAmount() && $this->getPercentShippingCost()) {
            $message = 'Veuillez entrer soit un pourcentage de remise ou un montant de remise, mais pas les deux';
            $context->buildViolation($message)
                    ->atPath('percent')
                    ->addViolation();
        }
    }
}
