<?php

namespace Lc\CaracoleBundle\Model\Order;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Lc\CaracoleBundle\Doctrine\Extension\FilterSectionInterface;
use Lc\CaracoleBundle\Model\Address\AddressInterface;
use Lc\CaracoleBundle\Model\Config\TaxRateInterface;
use Lc\CaracoleBundle\Model\Distribution\DistributionInterface;
use Lc\CaracoleBundle\Model\File\DocumentInterface;
use Lc\CaracoleBundle\Model\PointSale\PointSaleInterface;
use Lc\CaracoleBundle\Model\Section\SectionInterface;
use Lc\SovBundle\Model\Ticket\TicketInterface;
use Lc\CaracoleBundle\Model\User\VisitorInterface;
use Lc\SovBundle\Doctrine\Pattern\AbstractLightEntity;
use Lc\SovBundle\Model\User\UserInterface;

abstract class OrderShopModel extends AbstractLightEntity implements FilterSectionInterface, OrderShopInterface
{

    const DELIVERY_TYPE_HOME = 'home';
    const DELIVERY_TYPE_POINTSALE = 'point-sale';

    /**
     * @ORM\ManyToOne(targetEntity="Lc\SovBundle\Model\User\UserInterface", inversedBy="orderShops", fetch="EAGER")
     * @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
     */
    protected $user;

    /**
     * @ORM\ManyToOne(targetEntity="Lc\CaracoleBundle\Model\User\VisitorInterface", inversedBy="orders")
     */
    protected $visitor;

    /**
     * @ORM\ManyToOne(targetEntity="Lc\CaracoleBundle\Model\Address\AddressInterface")
     * @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
     */
    protected $invoiceAddress;

    /**
     * @ORM\Column(type="text", nullable=true)
     */
    protected $invoiceAddressText;

    /**
     * @ORM\Column(type="datetime", nullable=true)
     */
    protected $validationDate;

    /**
     * @ORM\Column(type="text", nullable=true)
     */
    protected $comment;

    /**
     * @ORM\Column(type="string", length=31, nullable=true)
     */
    protected $meanPayment;

    /**
     * @ORM\OneToMany(targetEntity="Lc\CaracoleBundle\Model\Order\OrderStatusHistoryInterface", mappedBy="orderShop", orphanRemoval=true, cascade={"persist"})
     */
    protected $orderStatusHistories;

    /**
     * @ORM\OneToMany(targetEntity="Lc\CaracoleBundle\Model\Order\OrderPaymentInterface", mappedBy="orderShop", orphanRemoval=true,cascade={"persist"})
     */
    protected $orderPayments;

    /**
     * @ORM\OneToMany(targetEntity="Lc\CaracoleBundle\Model\Order\OrderProductInterface", mappedBy="orderShop", cascade={"persist", "remove"}, orphanRemoval=true, fetch="EAGER")
     */
    protected $orderProducts;

    /**
     * @ORM\Column(type="text", nullable=true)
     */
    protected $deliveryInfos;

    /**
     * @ORM\ManyToOne(targetEntity="Lc\CaracoleBundle\Model\Order\OrderStatusInterface")
     * @ORM\JoinColumn(nullable=false)
     */
    protected $orderStatus;

    /**
     * @ORM\OneToMany(targetEntity="Lc\CaracoleBundle\Model\Order\OrderReductionCartInterface", mappedBy="orderShop", orphanRemoval=true)
     */
    protected $orderReductionCarts;

    /**
     * @ORM\OneToMany(targetEntity="Lc\CaracoleBundle\Model\Order\OrderReductionCreditInterface", mappedBy="orderShop", orphanRemoval=true)
     */
    protected $orderReductionCredits;

    /**
     * @ORM\ManyToMany(targetEntity="Lc\CaracoleBundle\Model\File\DocumentInterface", inversedBy="orderShops", cascade={"persist"})
     */
    protected $documents;

    /**
     * @ORM\OneToMany(targetEntity="Lc\SovBundle\Model\Ticket\TicketInterface", mappedBy="orderShop")
     */
    protected $tickets;

    /**
     * @ORM\ManyToOne(targetEntity="Lc\CaracoleBundle\Model\Section\SectionInterface", inversedBy="orderShops")
     * @ORM\JoinColumn(nullable=false)
     */
    protected $section;

    /**
     * @ORM\Column(type="integer", nullable=true)
     */
    protected $cycleId;

    /**
     * @ORM\ManyToOne(targetEntity="Lc\CaracoleBundle\Model\Distribution\DistributionInterface")
     * @ORM\JoinColumn(nullable=true)
     */
    protected $distribution;

    /**
     * @ORM\Column(type="datetime", nullable=true)
     */
    protected $orderShopCreatedAt;

    /**
     * @ORM\Column(type="integer", nullable=true)
     */
    protected $idValidOrder;
    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Address\Address")
     * @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
     */
    protected $deliveryAddress;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\PointSale\PointSale")
     */
    protected $deliveryPointSale;

    /**
     * @ORM\Column(type="text", nullable=true)
     */
    protected $deliveryAddressText;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    protected $deliveryType;

    /**
     * @ORM\Column(type="float", nullable=true)
     */
    protected $deliveryPrice;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Config\TaxRate")
     */
    protected $deliveryTaxRate;

    /**
     * @ORM\Column(type="string", length=20, nullable=true)
     */
    protected $reference;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Order\OrderShop", inversedBy="complementaryOrderShops")
     */
    protected $mainOrderShop;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Order\OrderShop", mappedBy="mainOrderShop")
     */
    protected $complementaryOrderShops;

    /**
     * @ORM\Column(type="boolean", nullable=true)
     */
    protected $declineComplementaryOrderShop;

    /**
     * @ORM\Column(type="boolean", nullable=true)
     */
    protected $orderAllowByAdmin;

    /**
     * @ORM\Column(type="integer", nullable=true)
     */
    protected $hasReach;

    /**
     * @ORM\Column(type="float", nullable=true)
     */
    protected $statTotal;

    /**
     * @ORM\Column(type="float", nullable=true)
     */
    protected $statTotalWithTax;

    /**
     * @ORM\Column(type="float", nullable=true)
     */
    protected $statTotalOrderProductsWithReductions;

    /**
     * @ORM\Column(type="float", nullable=true)
     */
    protected $statTotalOrderProductsWithTaxAndReductions;

    /**
     * @ORM\Column(type="float", nullable=true)
     */
    protected $statMarginOrderProductsWithReductions;

    /**
     * @ORM\Column(type="float", nullable=true)
     */
    protected $statDeliveryPriceWithReduction;

    /**
     * @ORM\Column(type="float", nullable=true)
     */
    protected $statDeliveryPriceWithTaxAndReduction;

    public function __construct()
    {
        $this->orderStatusHistories = new ArrayCollection();
        $this->orderPayments = new ArrayCollection();
        $this->orderProducts = new ArrayCollection();
        $this->orderReductionCarts = new ArrayCollection();
        $this->orderReductionCredits = new ArrayCollection();
        $this->documents = new ArrayCollection();
        $this->complementaryOrderShops = new ArrayCollection();
        $this->tickets = new ArrayCollection();
    }

    public function __toString()
    {
        if ($this->getValidationDate()) {
            return 'Commande du ' . $this->getValidationDate()->format('d/m/Y');
        } else {
            return 'Commande #' . $this->getId();
        }
    }

    public function getValidationDate(): ?\DateTimeInterface
    {
        return $this->validationDate;
    }

    public function setValidationDate(\DateTimeInterface $validationDate): self
    {
        $this->validationDate = $validationDate;

        return $this;
    }

    public function getUser(): ?UserInterface
    {
        return $this->user;
    }

    public function setUser(?UserInterface $user): self
    {
        $this->user = $user;

        return $this;
    }

    public function getInvoiceAddress(): ?AddressInterface
    {
        return $this->invoiceAddress;
    }

    public function setInvoiceAddress(?AddressInterface $invoiceAddress): self
    {
        $this->invoiceAddress = $invoiceAddress;

        return $this;
    }

    public function getInvoiceAddressText(): ?string
    {
        return $this->invoiceAddressText;
    }

    public function setInvoiceAddressText(string $invoiceAddressText): self
    {
        $this->invoiceAddressText = $invoiceAddressText;

        return $this;
    }

    public function getComment(): ?string
    {
        return $this->comment;
    }

    public function setComment(?string $comment): self
    {
        $this->comment = $comment;

        return $this;
    }

    public function getMeanPayment(): ?string
    {
        return $this->meanPayment;
    }

    public function setMeanPayment(string $meanPayment): self
    {
        $this->meanPayment = $meanPayment;

        return $this;
    }

    /**
     * @return Collection|OrderStatusHistoryInterface[]
     */
    public function getOrderStatusHistories(): Collection
    {
        return $this->orderStatusHistories;
    }

    public function addOrderStatusHistory(OrderStatusHistoryInterface $orderStatusHistory): self
    {
        if (!$this->orderStatusHistories->contains($orderStatusHistory)) {
            $this->orderStatusHistories[] = $orderStatusHistory;
            $orderStatusHistory->setOrderShop($this);
        }

        return $this;
    }

    public function removeOrderStatusHistory(OrderStatusHistoryInterface $orderStatusHistory): self
    {
        if ($this->orderStatusHistories->contains($orderStatusHistory)) {
            $this->orderStatusHistories->removeElement($orderStatusHistory);
            // set the owning side to null (unless already changed)
            if ($orderStatusHistory->getOrderShop() === $this) {
                $orderStatusHistory->setOrderShop(null);
            }
        }

        return $this;
    }

    /**
     * @return Collection|OrderPaymentInterface[]
     */
    public function getOrderPayments($meanPayment = null): Collection
    {
        if ($meanPayment) {
            $orderPaymentsReturn = new ArrayCollection();

            foreach ($this->orderPayments as $orderPayment) {
                if ($orderPayment->getMeanPayment() == $meanPayment) {
                    $orderPaymentsReturn[] = $orderPayment;
                }
            }

            return $orderPaymentsReturn;
        }

        return $this->orderPayments;
    }

    public function addOrderPayment(OrderPaymentInterface $orderPayment): self
    {
        if (!$this->orderPayments->contains($orderPayment)) {
            $this->orderPayments[] = $orderPayment;
            $orderPayment->setOrderShop($this);
        }

        return $this;
    }

    public function removeOrderPayment(OrderPaymentInterface $orderPayment): self
    {
        if ($this->orderPayments->contains($orderPayment)) {
            $this->orderPayments->removeElement($orderPayment);
            // set the owning side to null (unless already changed)
            if ($orderPayment->getOrderShop() === $this) {
                $orderPayment->setOrderShop(null);
            }
        }

        return $this;
    }

    /**
     * @return Collection|OrderProductInterface[]
     */
    public function getOrderProducts(): Collection
    {
        return $this->orderProducts;
    }

    public function addOrderProduct(OrderProductInterface $orderProduct): self
    {
        if (!$this->orderProducts->contains($orderProduct)) {
            $this->orderProducts[] = $orderProduct;
            $orderProduct->setOrderShop($this);
        }

        return $this;
    }

    public function removeOrderProduct(OrderProductInterface $orderProduct): self
    {
        if ($this->orderProducts->contains($orderProduct)) {
            $this->orderProducts->removeElement($orderProduct);
            // set the owning side to null (unless already changed)
            if ($orderProduct->getOrderShop() === $this) {
                $orderProduct->setOrderShop(null);
            }
        }

        return $this;
    }

    public function getVisitor(): ?VisitorInterface
    {
        return $this->visitor;
    }

    public function setVisitor(?VisitorInterface $visitor): self
    {
        $this->visitor = $visitor;

        return $this;
    }

    public function getDeliveryInfos(): ?string
    {
        return $this->deliveryInfos;
    }

    public function setDeliveryInfos(?string $deliveryInfos): self
    {
        $this->deliveryInfos = $deliveryInfos;

        return $this;
    }


    public function getOrderStatus(): ?OrderStatusInterface
    {
        return $this->orderStatus;
    }

    public function setOrderStatusProtected(?OrderStatusInterface $orderStatus): self
    {
        $this->orderStatus = $orderStatus;

        return $this;
    }

    /**
     * @return Collection|OrderReductionCartInterface[]
     */
    public function getOrderReductionCarts(): Collection
    {
        return $this->orderReductionCarts;
    }

    public function addOrderReductionCart(OrderReductionCartInterface $orderReductionCart): self
    {
        if (!$this->orderReductionCarts->contains($orderReductionCart)) {
            $this->orderReductionCarts[] = $orderReductionCart;
            $orderReductionCart->setOrderShop($this);
        }

        return $this;
    }

    public function removeOrderReductionCart(OrderReductionCartInterface $orderReductionCart): self
    {
        if ($this->orderReductionCarts->contains($orderReductionCart)) {
            $this->orderReductionCarts->removeElement($orderReductionCart);
            // set the owning side to null (unless already changed)
            if ($orderReductionCart->getOrderShop() === $this) {
                $orderReductionCart->setOrderShop(null);
            }
        }

        return $this;
    }

    /**
     * @return Collection|OrderReductionCreditInterface[]
     */
    public function getOrderReductionCredits(): Collection
    {
        return $this->orderReductionCredits;
    }

    public function addOrderReductionCredit(OrderReductionCreditInterface $orderReductionCredit): self
    {
        if (!$this->orderReductionCredits->contains($orderReductionCredit)) {
            $this->orderReductionCredits[] = $orderReductionCredit;
            $orderReductionCredit->setOrderShop($this);
        }

        return $this;
    }

    public function removeOrderReductionCredit(OrderReductionCreditInterface $orderReductionCredit): self
    {
        if ($this->orderReductionCredits->contains($orderReductionCredit)) {
            $this->orderReductionCredits->removeElement($orderReductionCredit);
            // set the owning side to null (unless already changed)
            if ($orderReductionCredit->getOrderShop() === $this) {
                $orderReductionCredit->setOrderShop(null);
            }
        }

        return $this;
    }

    /**
     * @return Collection|DocumentInterface[]
     */
    public function getDocuments(): Collection
    {
        return $this->documents;
    }

    public function addDocument(DocumentInterface $document): self
    {
        if (!$this->documents->contains($document)) {
            $this->documents[] = $document;
        }

        return $this;
    }

    public function removeDocument(DocumentInterface $document): self
    {
        if ($this->documents->contains($document)) {
            $this->documents->removeElement($document);
        }

        return $this;
    }

    /**
     * @return Collection|TicketInterface[]
     */
    public function getTickets(): Collection
    {
        return $this->tickets;
    }

    public function addTicket(TicketInterface $ticket): self
    {
        if (!$this->tickets->contains($ticket)) {
            $this->tickets[] = $ticket;
            $ticket->setOrderShop($this);
        }

        return $this;
    }

    public function removeTicket(TicketInterface $ticket): self
    {
        if ($this->tickets->contains($ticket)) {
            $this->tickets->removeElement($ticket);
            // set the owning side to null (unless already changed)
            if ($ticket->getOrderShop() === $this) {
                $ticket->setOrderShop(null);
            }
        }

        return $this;
    }

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

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

        return $this;
    }

    public function getCycleId(): ?int
    {
        return $this->cycleId;
    }

    public function setCycleId(?int $cycleId): self
    {
        $this->cycleId = $cycleId;

        return $this;
    }

    public function getDistribution(): ?DistributionInterface
    {
        return $this->distribution;
    }

    public function setDistribution(?DistributionInterface $distribution): self
    {
        $this->distribution = $distribution;

        return $this;
    }

    public function getOrderShopCreatedAt(): ?\DateTimeInterface
    {
        return $this->orderShopCreatedAt;
    }

    public function setOrderShopCreatedAt(?\DateTimeInterface $orderShopCreatedAt): self
    {
        $this->orderShopCreatedAt = $orderShopCreatedAt;

        return $this;
    }

    public function getIdValidOrder(): ?int
    {
        return $this->idValidOrder;
    }

    public function setIdValidOrder(?int $idValidOrder): self
    {
        $this->idValidOrder = $idValidOrder;

        return $this;
    }


    public function getDeliveryAddress(): ?AddressInterface
    {
        return $this->deliveryAddress;
    }

    public function setDeliveryAddress(?AddressInterface $deliveryAddress): self
    {
        $this->deliveryAddress = $deliveryAddress;

        return $this;
    }

    public function getDeliveryAddressText(): ?string
    {
        return $this->deliveryAddressText;
    }

    public function setDeliveryAddressText(string $deliveryAddressText): self
    {
        $this->deliveryAddressText = $deliveryAddressText;

        return $this;
    }

    public function getDeliveryPointSale(): ?PointSaleInterface
    {
        return $this->deliveryPointSale;
    }

    public function setDeliveryPointSale(?PointSaleInterface $deliveryPointSale): self
    {
        $this->deliveryPointSale = $deliveryPointSale;

        return $this;
    }

    public function getDeliveryType(): ?string
    {
        return $this->deliveryType;
    }

    public function setDeliveryType(?string $deliveryType): self
    {
        $this->deliveryType = $deliveryType;

        return $this;
    }

    public function getDeliveryPrice(): ?float
    {
        return $this->deliveryPrice;
    }

    public function setDeliveryPrice(?float $deliveryPrice): self
    {
        $this->deliveryPrice = $deliveryPrice;

        return $this;
    }

    public function getDeliveryTaxRate(): ?TaxRateInterface
    {
        return $this->deliveryTaxRate;
    }

    public function setDeliveryTaxRate(?TaxRateInterface $deliveryTaxRate): self
    {
        $this->deliveryTaxRate = $deliveryTaxRate;

        return $this;
    }

    public function getReference(): ?string
    {
        return $this->reference;
    }

    public function setReference(?string $reference): self
    {
        $this->reference = $reference;

        return $this;
    }

    public function getMainOrderShop(): ?self
    {
        return $this->mainOrderShop;
    }

    public function setMainOrderShop(?self $mainOrderShop): self
    {
        $this->mainOrderShop = $mainOrderShop;

        return $this;
    }

    /**
     * @return Collection|OrderShopInterface[]
     */
    public function getComplementaryOrderShops(): Collection
    {
        $arrayComplementaryOrderShops = new ArrayCollection();
        foreach ($this->complementaryOrderShops as $complementaryOrderShop) {
            $arrayComplementaryOrderShops[] = $complementaryOrderShop;
        }
        return $arrayComplementaryOrderShops;
    }

    public function addComplementaryOrderShop(self $complementaryOrderShop): self
    {
        if (!$this->complementaryOrderShops->contains($complementaryOrderShop)) {
            $this->complementaryOrderShops[] = $complementaryOrderShop;
            $complementaryOrderShop->setMainOrderShop($this);
        }

        return $this;
    }

    public function removeComplementaryOrderShop(self $complementaryOrderShop): self
    {
        if ($this->complementaryOrderShops->contains($complementaryOrderShop)) {
            $this->complementaryOrderShops->removeElement($complementaryOrderShop);
            // set the owning side to null (unless already changed)
            if ($complementaryOrderShop->getMainOrderShop() === $this) {
                $complementaryOrderShop->setMainOrderShop(null);
            }
        }

        return $this;
    }

    public function getDeclineComplementaryOrderShop(): ?bool
    {
        return $this->declineComplementaryOrderShop;
    }

    public function setDeclineComplementaryOrderShop(?bool $declineComplementaryOrderShop): self
    {
        $this->declineComplementaryOrderShop = $declineComplementaryOrderShop;

        return $this;
    }

    public function getOrderAllowByAdmin(): ?bool
    {
        return $this->orderAllowByAdmin;
    }

    public function setOrderAllowByAdmin(?bool $orderAllowByAdmin): self
    {
        $this->orderAllowByAdmin = $orderAllowByAdmin;

        return $this;
    }

    public function getHasReach(): ?int
    {
        return $this->hasReach;
    }

    public function setHasReach(?int $hasReach): self
    {
        $this->hasReach = $hasReach;

        return $this;
    }


    public function getStatTotal(): ?float
    {
        return $this->statTotal;
    }

    public function setStatTotal(?float $statTotal): self
    {
        $this->statTotal = $statTotal;

        return $this;
    }

    public function getStatTotalWithTax(): ?float
    {
        return $this->statTotalWithTax;
    }

    public function setStatTotalWithTax(?float $statTotalWithTax): self
    {
        $this->statTotalWithTax = $statTotalWithTax;

        return $this;
    }

    public function getStatTotalOrderProductsWithReductions(): ?float
    {
        return $this->statTotalOrderProductsWithReductions;
    }

    public function setStatTotalOrderProductsWithReductions(?float $statTotalOrderProductsWithReductions): self
    {
        $this->statTotalOrderProductsWithReductions = $statTotalOrderProductsWithReductions;

        return $this;
    }

    public function getStatTotalOrderProductsWithTaxAndReductions(): ?float
    {
        return $this->statTotalOrderProductsWithTaxAndReductions;
    }

    public function setStatTotalOrderProductsWithTaxAndReductions(?float $statTotalOrderProductsWithTaxAndReductions): self
    {
        $this->statTotalOrderProductsWithTaxAndReductions = $statTotalOrderProductsWithTaxAndReductions;

        return $this;
    }

    public function getStatMarginOrderProductsWithReductions(): ?float
    {
        return $this->statMarginOrderProductsWithReductions;
    }

    public function setStatMarginOrderProductsWithReductions(?float $statMarginOrderProductsWithReductions): self
    {
        $this->statMarginOrderProductsWithReductions = $statMarginOrderProductsWithReductions;

        return $this;
    }

    public function getStatDeliveryPriceWithReduction(): ?float
    {
        return $this->statDeliveryPriceWithReduction;
    }

    public function setStatDeliveryPriceWithReduction(?float $statDeliveryPriceWithReduction): self
    {
        $this->statDeliveryPriceWithReduction = $statDeliveryPriceWithReduction;

        return $this;
    }

    public function getStatDeliveryPriceWithTaxAndReduction(): ?float
    {
        return $this->statDeliveryPriceWithTaxAndReduction;
    }

    public function setStatDeliveryPriceWithTaxAndReduction(?float $statDeliveryPriceWithTaxAndReduction): self
    {
        $this->statDeliveryPriceWithTaxAndReduction = $statDeliveryPriceWithTaxAndReduction;

        return $this;
    }
}