<?php
// Copyright (c) Pickware GmbH. All rights reserved.
// This file is part of software that is released under a proprietary license.
// You must not copy, modify, distribute, make publicly available, or execute
// its contents or parts thereof without express permission by the copyright
// holder, unless otherwise permitted by law.

/**
 * @Shopware\noEncryption
 */

namespace Shopware\CustomModels\ViisonShippingCommon\Shipment;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Shopware\Components\Model\ModelEntity;
use Shopware\CustomModels\ViisonShippingCommon\Product\Product;
use Shopware\Models\Order\Order;
use Shopware\Plugins\ViisonCommon\Classes\Util\Doctrine as DoctrineUtil;
use \DateTime;
use \InvalidArgumentException;

/**
 * @ORM\MappedSuperclass
 *
 * Note: Every adapter needs to specify the ORM\Table and ORM\Entity annotations in their subclasses of this model:
 *
 *       ORM\Entity(repositoryClass="Shopware\CustomModels\ADAPTER_NAME\Shipment\Repository")
 *       ORM\Table(name="s_plugin_ADAPTER_NAME_shipments")
 */
abstract class Shipment extends ModelEntity
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    protected $id;

    /**
     * @var int
     *
     * @ORM\Column(name="productId", type="integer", nullable=false)
     */
    protected $productId;

    /**
     * OWNING SIDE
     *
     * @var Product
     *
     * Note: This definition has no annotations, because they have to be defined in the subclasses. Re-implement this
     *       property again in your subclass with the following annotation (replace ADAPTER_NAME):
     *
     *       ORM\ManyToOne(targetEntity="Shopware\CustomModels\ADAPTER_NAME\Product\Product")
     *       ORM\JoinColumn(name="productId", referencedColumnName="id", onDelete="SET NULL")
     */
    protected $product;

    /**
     * @var int
     *
     * @ORM\Column(name="orderId", type="integer", nullable=true)
     */
    protected $orderId;

    /**
     * OWNING SIDE
     *
     * @var Order
     *
     * @ORM\ManyToOne(targetEntity="\Shopware\Models\Order\Order")
     * @ORM\JoinColumn(name="orderId", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $order;

    /**
     * @var string
     *
     * @ORM\Column(name="trackingCode", type="string", nullable=true)
     */
    protected $trackingCode;

    /**
     * @var string
     *
     * @ORM\Column(name="customerAddress", type="string", nullable=true)
     */
    protected $customerAddress;

    /**
     * @var bool
     *
     * @ORM\Column(name="returnShipment", type="boolean", nullable=false)
     */
    protected $returnShipment = false;

    /**
     * @var float
     *
     * @ORM\Column(name="weight", type="decimal", precision=10, scale=3, nullable=true)
     */
    protected $weight;

    /**
     * @var DateTime
     *
     * @ORM\Column(name="created", type="datetime", nullable=false)
     */
    protected $created;

    /**
     * @var bool
     */
    protected $isCashOnDeliveryShipment = false;

    /**
     * INVERSE SIDE
     *
     * @var ArrayCollection
     *
     * Note: This definition has no annotations, because they have to be defined in the subclasses. Re-implement this
     *       property again in your subclass with the following annotation (replace ADAPTER_NAME):
     *
     *       ORM\OneToMany(targetEntity="Shopware\CustomModels\ADAPTER_NAME\Shipment\Document", mappedBy="shipment")
     */
    protected $documents;

    public function __construct()
    {
        $this->created = new DateTime();
        $this->documents = new ArrayCollection();
    }

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

    /**
     * @return Product
     */
    public function getProduct()
    {
        return $this->product;
    }

    /**
     * @param Product $product
     * @throws InvalidArgumentException
     */
    public function setProduct(Product $product)
    {
        // Make sure the passed product is part of the same namespace as this shipment
        if (!DoctrineUtil::customModelsShareNamespace($product, $this)) {
            throw new InvalidArgumentException(
                sprintf('The namespace of the provided $product (%s) must match the namespace of $this shipment (%s).', get_class($product), get_class($this))
            );
        }

        $this->product = $product;
    }

    /**
     * @return Order|null
     */
    public function getOrder()
    {
        return $this->order;
    }

    /**
     * @param Order|null $order
     */
    public function setOrder(Order $order = null)
    {
        $this->order = $order;
    }

    /**
     * @return string|null
     */
    public function getTrackingCode()
    {
        return $this->trackingCode;
    }

    /**
     * @param string|null $trackingCode
     */
    public function setTrackingCode($trackingCode)
    {
        $this->trackingCode = $trackingCode;
    }

    /**
     * @return string|null
     */
    public function getCustomerAddress()
    {
        return $this->customerAddress;
    }

    /**
     * @param string|null $customerAddress
     */
    public function setCustomerAddress($customerAddress)
    {
        $this->customerAddress = $customerAddress;
    }

    /**
     * @return bool
     */
    public function isReturnShipment()
    {
        return $this->returnShipment;
    }

    /**
     * @param bool $returnShipment
     */
    public function setReturnShipment($returnShipment)
    {
        $this->returnShipment = $returnShipment;
    }

    /**
     * @return float|null
     */
    public function getWeight()
    {
        return $this->weight;
    }

    /**
     * @param float|null $weight
     */
    public function setWeight($weight)
    {
        $this->weight = $weight;
    }

    /**
     * @return DateTime
     */
    public function getCreated()
    {
        return $this->created;
    }

    /**
     * @param DateTime $created
     */
    public function setCreated(DateTime $created)
    {
        $this->created = $created;
    }

    /**
     * @return ArrayCollection
     */
    public function getDocuments()
    {
        return $this->documents;
    }

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

    /**
     * @param bool $isCashOnDeliveryShipment
     */
    public function setIsCashOnDeliveryShipment($isCashOnDeliveryShipment)
    {
        $this->isCashOnDeliveryShipment = $isCashOnDeliveryShipment;
    }

    /**
     * @param Document $document
     * @throws InvalidArgumentException
     */
    public function addDocument(Document $document)
    {
        if ($this->documents->contains($document)) {
            return;
        }

        // Make sure the passed document is part of the same namespace as this shipment
        if (!DoctrineUtil::customModelsShareNamespace($document, $this)) {
            throw new InvalidArgumentException(
                sprintf('The namespace of the provided $document (%s) must match the namespace of $this shipment (%s).', get_class($document), get_class($this))
            );
        }

        $this->documents->add($document);
        $document->setShipment($this);
    }

    /**
     * Iterate over the documents and get the document by type.
     *
     * @param $type
     * @return Document
     */
    public function getDocumentByType($type)
    {
        $documents = $this->getDocuments();

        /** @var Document $document */
        foreach ($documents as $document) {
            if ($document->getType() === $type) {
                return $document;
            }
        }
    }
}
