<?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.

namespace Shopware\CustomModels\ViisonPickwareMobile\PickProfile;

use DateInterval;
use DateTime;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use InvalidArgumentException;
use Shopware\Components\Model\ModelEntity;
use Shopware\Plugins\ViisonPickwareMobile\Components\PickingOrderFilter\StockBasedFilterConfiguration;

/**
 * @ORM\Entity()
 * @ORM\Table(name="pickware_wms_pick_profiles")
 */
class PickProfile extends ModelEntity
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\GeneratedValue(strategy="IDENTITY")
     * @ORM\Id
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", nullable=false)
     */
    private $name;

    /**
     * @var string
     *
     * @ORM\Column(name="stockBasedOrderFilterMode", type="integer", nullable=false)
     */
    private $stockBasedOrderFilterMode = StockBasedFilterConfiguration::FILTER_MODE_OFF;

    /**
     * @var string
     *
     * @ORM\Column(name="advanceDaysForPreOrderedItems", type="integer", nullable=false)
     */
    private $advanceDaysForPreOrderedItems = 3;

    /**
     * @var string
     *
     * @ORM\Column(name="encodedOrderFilterQueryConditions", type="text", nullable=true)
     */
    private $encodedOrderFilterQueryConditions;

    /**
     * INVERSE SIDE
     *
     * @var ArrayCollection
     *
     * @ORM\OneToMany(targetEntity="Shopware\CustomModels\ViisonPickwareMobile\PickProfile\PickProfilePrioritizedDispatchMethod", mappedBy="pickProfile", cascade={"persist"})
     */
    private $prioritizedDispatchMethods;

    /**
     * INVERSE SIDE
     *
     * @var ArrayCollection
     *
     * @ORM\OneToMany(targetEntity="Shopware\CustomModels\ViisonPickwareMobile\PickProfile\PickProfilePrioritizedPaymentMethod", mappedBy="pickProfile", cascade={"persist"})
     */
    private $prioritizedPaymentMethods;

    /**
     * INVERSE SIDE
     *
     * @var ArrayCollection
     *
     * @ORM\OneToMany(targetEntity="Shopware\CustomModels\ViisonPickwareMobile\PickProfile\PickProfileStockBasedOrderFilterExemptDispatchMethod", mappedBy="pickProfile", cascade={"persist"})
     */
    private $stockBasedOrderFilterExemptDispatchMethods;

    public function __construct()
    {
        $this->prioritizedDispatchMethods = new ArrayCollection();
        $this->prioritizedPaymentMethods = new ArrayCollection();
        $this->stockBasedOrderFilterExemptDispatchMethods = new ArrayCollection();
    }

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

    /**
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @param string $name
     */
    public function setName($name)
    {
        $this->name = $name;
    }

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

    /**
     * @param int $stockBasedOrderFilterMode
     * @throws InvalidArgumentException
     */
    public function setStockBasedOrderFilterMode($stockBasedOrderFilterMode)
    {
        if (!in_array($stockBasedOrderFilterMode, StockBasedFilterConfiguration::VALID_FILTER_MODES)) {
            throw new InvalidArgumentException(sprintf(
                'The given stock based filter mode %s is invalid. Must be one of: %s',
                $stockBasedOrderFilterMode,
                implode(', ', StockBasedFilterConfiguration::VALID_FILTER_MODES)
            ));
        }

        $this->stockBasedOrderFilterMode = $stockBasedOrderFilterMode;
    }

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

    /**
     * @param int $advanceDaysForPreOrderedItems
     * @throws InvalidArgumentException
     */
    public function setAdvanceDaysForPreOrderedItems($advanceDaysForPreOrderedItems)
    {
        if ($advanceDaysForPreOrderedItems < 0) {
            throw new InvalidArgumentException('PickProfile.advanceDaysForPreOrderedItems must not be less than zero.');
        }

        $this->advanceDaysForPreOrderedItems = $advanceDaysForPreOrderedItems;
    }

    /**
     * @return string
     */
    public function getEncodedOrderFilterQueryConditions()
    {
        return $this->encodedOrderFilterQueryConditions;
    }

    /**
     * @return array
     */
    public function getOrderFilterQueryConditions()
    {
        return self::decodeOrderFilterQueryConditions($this->getEncodedOrderFilterQueryConditions()) ?: [];
    }

    /**
     * @param array|null $orderFilterQueryConditions
     */
    public function setOrderFilterQueryConditions(array $orderFilterQueryConditions = null)
    {
        if (is_array($orderFilterQueryConditions) && count($orderFilterQueryConditions) > 0) {
            $this->encodedOrderFilterQueryConditions = json_encode($orderFilterQueryConditions, JSON_PRETTY_PRINT);
        } else {
            $this->encodedOrderFilterQueryConditions = null;
        }
    }

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

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

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

    /**
     * @param int $dispatchMethodId
     * @return bool
     */
    public function prioritizesDispatchMethodWithId($dispatchMethodId)
    {
        foreach ($this->getPrioritizedDispatchMethods() as $prioritizedDispatchMethod) {
            if ($prioritizedDispatchMethod->getDispatchMethod()->getId() == $dispatchMethodId) {
                return true;
            }
        }

        return false;
    }

    /**
     * @param int $paymentMethodId
     * @return bool
     */
    public function prioritizesPaymentMethodWithId($paymentMethodId)
    {
        foreach ($this->getPrioritizedPaymentMethods() as $prioritizedPaymentMethod) {
            if ($prioritizedPaymentMethod->getPaymentMethod()->getId() == $paymentMethodId) {
                return true;
            }
        }

        return false;
    }

    /**
     * @return DateTime
     */
    public function getEarliestReleaseDateForPreOrderedItems()
    {
        return self::createEarliestReleaseDateForPreOrderedItems($this->getAdvanceDaysForPreOrderedItems());
    }

    /**
     * @param string $jsonEncodedQueryConditions
     * @return array|null
     */
    public static function decodeOrderFilterQueryConditions($jsonEncodedQueryConditions)
    {
        if (!is_string($jsonEncodedQueryConditions) || mb_strlen($jsonEncodedQueryConditions) === 0) {
            return null;
        }

        return json_decode($jsonEncodedQueryConditions, true);
    }

    /**
     * @param int $advanceDaysForPreOrderedItems
     * @return DateTime
     */
    public static function createEarliestReleaseDateForPreOrderedItems($advanceDaysForPreOrderedItems)
    {
        $earliestReleaseDate = new DateTime();
        if ($advanceDaysForPreOrderedItems > 0) {
            $earliestReleaseDate = $earliestReleaseDate->add(
                new DateInterval('P' . $advanceDaysForPreOrderedItems . 'D')
            );
        }

        return $earliestReleaseDate;
    }
}
