<?php

namespace Leadlion\AutogedalWarehouses\Model;

use Leadlion\AutogedalWarehouses\Model\ResourceModel\Warehouse as WarehousesResourceModel;
use Magento\Quote\Model\Quote\Address;
use Magento\Rule\Model\AbstractModel;

class Warehouse extends AbstractModel
{
    const URGENT_CURRIER = 1;
    const FAN_CURRIER = 2;
    const DPD = 3;
    const GLS = 4;
    const DRAGON_STAR = 5;
    const X_CURIER = 6;
    const NEMO_EXPRESS = 7;
    const SAMEDAY = 8;
    const PACKETA_FAN_COURIER = 9;
    const PACKETA_SAMEDAY  = 10;
    
    protected $_eventPrefix = 'Leadlion_autogedalwarehouses';
    protected $_eventObject = 'rule';
    protected $condCombineFactory;
    protected $condProdCombineF;
    protected $validatedAddresses = [];
    protected $_selectProductIds;
    protected $_displayProductIds;

    public function __construct(
        \Magento\Framework\Model\Context $context,
        \Magento\Framework\Registry $registry,
        \Magento\Framework\Data\FormFactory $formFactory,
        \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
        \Magento\CatalogRule\Model\Rule\Condition\CombineFactory $condCombineFactory,
        \Magento\SalesRule\Model\Rule\Condition\Product\CombineFactory $condProdCombineF,
        \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
        \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
        array $data = []
    ) {
        $this->condCombineFactory = $condCombineFactory;
        $this->condProdCombineF = $condProdCombineF;
        parent::__construct($context, $registry, $formFactory, $localeDate, $resource, $resourceCollection, $data);
    }

    protected function _construct()
    {
        parent::_construct();
        $this->_init(WarehousesResourceModel::class);
        $this->setIdFieldName('warehouse_id');
    }

    public function getConditionsInstance()
    {
        return $this->condCombineFactory->create();
    }

    public function getActionsInstance()
    {
        return $this->condCombineFactory->create();
    }

    public function hasIsValidForAddress($address)
    {
        $addressId = $this->_getAddressId($address);
        return isset($this->validatedAddresses[$addressId]) ? true : false;
    }

    public function setIsValidForAddress($address, $validationResult)
    {
        $addressId = $this->_getAddressId($address);
        $this->validatedAddresses[$addressId] = $validationResult;
        return $this;
    }

    public function getIsValidForAddress($address)
    {
        $addressId = $this->_getAddressId($address);
        return isset($this->validatedAddresses[$addressId]) ? $this->validatedAddresses[$addressId] : false;
    }

    private function _getAddressId($address)
    {
        if ($address instanceof Address) {
            return $address->getId();
        }
        return $address;
    }

    public function getConditionsFieldSetId($formName = '')
    {
        return $formName . 'rule_conditions_fieldset_' . $this->getId();
    }

    public function getMatchProductIds()
    {    
        $productCollection = \Magento\Framework\App\ObjectManager::getInstance()->create(
            '\Magento\Catalog\Model\ResourceModel\Product\Collection'
        );
        $productFactory = \Magento\Framework\App\ObjectManager::getInstance()->create(
            '\Magento\Catalog\Model\ProductFactory'
        );
        $this->_productIds = [];
        $this->setCollectedAttributes([]);
        $this->getConditions()->collectValidatedAttributes($productCollection);
        \Magento\Framework\App\ObjectManager::getInstance()->create(
            '\Magento\Framework\Model\ResourceModel\Iterator'
        )->walk(
            $productCollection->getSelect(),
            [[$this, 'callbackValidateProduct']],
            [
                'attributes' => $this->getCollectedAttributes(),
                'product' => $productFactory->create()
            ]
        );
        return $this->_productIds;
    }
    /**
    * Callback function for product matching
    *
    * @param array $args
    * @return void
    */
    public function callbackValidateProduct($args)
    {
        $product = clone $args['product'];
        $product->setData($args['row']);
        $websites = $this->_getWebsitesMap();
        foreach ($websites as $websiteId => $defaultStoreId) {
            $product->setStoreId($defaultStoreId);
            if ($this->getConditions()->validate($product)) {
                $this->_productIds[] = $product->getId();
            }
        }
    }
    /**
    * Prepare website map
    *
    * @return array
    */
    protected function _getWebsitesMap()
    {
        $map = [];
        $websites = \Magento\Framework\App\ObjectManager::getInstance()->create(
            '\Magento\Store\Model\StoreManagerInterface'
        )->getWebsites();
        foreach ($websites as $website) {
            // Continue if website has no store to be able to create catalog rule for website without store
            if ($website->getDefaultStore() === null) {
                continue;
            }
            $map[$website->getId()] = $website->getDefaultStore()->getId();
        }
        return $map;
    }

    public static function getAvailableStatic()
    {
        $availableCarriers = [
            self::URGENT_CURRIER => __('Urgent Cargus'),
            self::DPD => __('DPD'),
            self::DRAGON_STAR => __('Dragon Star'),
            self::SAMEDAY => __('Sameday Courier'),
            self::PACKETA_FAN_COURIER => __('Packeta Fan Courier'),
            self::PACKETA_SAMEDAY => __('Packeta Sameday'),
            self::GLS => __('Gls')
        ];

        return $availableCarriers;
    }

    /**
     * Get phone
     *
     * @return string|null
     */
    public function getPhone()
    {
        return $this->getData('phone');
    }

    /**
     * Set phone
     *
     * @param string $phone
     * @return $this
     */
    public function setPhone($phone)
    {
        return $this->setData('phone', $phone);
    }

    /**
     * Get city
     *
     * @return string|null
     */
    public function getCity()
    {
        return $this->getData('city');
    }

    /**
     * Set city
     *
     * @param string $city
     * @return $this
     */
    public function setCity($city)
    {
        return $this->setData('city', $city);
    }

    /**
     * Get zip code
     *
     * @return string|null
     */
    public function getZipCode()
    {
        return $this->getData('zip_code');
    }

    /**
     * Set zip code
     *
     * @param string $zipCode
     * @return $this
     */
    public function setZipCode($zipCode)
    {
        return $this->setData('zip_code', $zipCode);
    }
}
