<?php

namespace Magetop\Agency\Helper;

use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\UrlInterface;
use Magetop\Agency\Model\ResourceModel\Items\CollectionFactory as ItemsCollection;
use Magetop\Agency\Model\ResourceModel\Quote\CollectionFactory as QuoteCollection;
use Magetop\Agency\Model\ResourceModel\Data\CollectionFactory as DataCollection;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory as ProductCollection;
use Magento\Framework\Mail\Template\TransportBuilder;
use Magento\Framework\Translate\Inline\StateInterface;
use Magento\Framework\App\Area;
use Magento\ConfigurableProduct\Model\Product\Type\Configurable as ConfigurableCollection;

class Data extends \Magento\Framework\App\Helper\AbstractHelper
{

    protected $_allowedProductTypes = ['simple', 'virtual', 'configurable'];
    /**
     * @var \Magento\Framework\App\Config\ScopeConfigInterface
     */
    protected $_scopeConfig;

    /**
     * @var \Magento\Framework\App\RequestInterface
     */
    protected $_request;

    /**
     * @var \Magento\Store\Model\StoreManagerInterface
     */
    protected $_storeManager;

    /**
     * @var \Magento\Framework\Message\ManagerInterface
     */
    protected $_messageManager;

    /**
     * @var \Magento\Customer\Model\Session
     */
    protected $_customerSession;

    /**
     * @var \Magento\Framework\Filesystem
     */
    protected $_filesystem;

    /**
     * @var \Magento\Framework\Data\Form\FormKey
     */
    protected $_formKey;

    /**
     * @var \Magento\Framework\Pricing\Helper\Data
     */
    protected $_currency;

    /**
     * @var \Magento\Framework\App\ResourceConnection
     */
    protected $_resource;

    /**
     * @var \Magento\MediaStorage\Model\File\UploaderFactory
     */
    protected $_fileUploader;

    /**
     * @var \Magento\Catalog\Model\ProductFactory
     */
    protected $_product;

    /**
     * @var \Magento\Checkout\Model\Cart
     */
    protected $_cart;

    /**
     * @var \Magetop\Agency\Model\ItemsFactory
     */
    protected $_items;

    /**
     * @var ItemsCollection
     */
    protected $_itemsCollection;

    /**
     * @var QuoteCollection
     */
    protected $_quoteCollection;

    /**
     * @var ProductCollection
     */
    protected $_productCollection;

    /**
     * @var ConfigurableCollection
     */
    protected $_configurableCollection;
    
    /**
     * @var Option
     */
    protected $_customOptions;

    /**
     * __construct
     *
     * @param \Magento\Framework\App\Helper\Context $context
     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
     * @param \Magento\Framework\Message\ManagerInterface $messageManager
     * @param \Magento\Customer\Model\Session $customerSession
     * @param \Magento\Framework\Filesystem $filesystem
     * @param \Magento\Framework\Data\Form\FormKey $formKey
     * @param \Magento\Framework\Pricing\Helper\Data $currency
     * @param \Magento\Framework\App\ResourceConnection $resource
     * @param \Magento\MediaStorage\Model\File\UploaderFactory $fileUploaderFactory
     * @param \Magento\Catalog\Model\ProductFactory $productFactory
     * @param \Magento\Checkout\Model\Cart $cart
     * @param \Magetop\Agency\Model\ItemsFactory $itemsFactory
     * @param \Magetop\Agency\Model\AssociatesFactory $associatesFactory
     * @param ItemsCollection $itemsCollectionFactory
     * @param QuoteCollection $quoteCollectionFactory
     * @param ProductCollection $productCollectionFactory
     * @param \Magento\Framework\Registry $coreRegistry
     * @param \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry
     */
    public function __construct(
        \Magento\Framework\App\Helper\Context $context,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\Message\ManagerInterface $messageManager,
        \Magento\Customer\Model\Session $customerSession,
        \Magento\Customer\Model\CustomerFactory $customer,
        \Magento\Framework\Filesystem $filesystem,
        \Magento\Framework\Data\Form\FormKey $formKey,
        \Magento\Framework\Pricing\Helper\Data $currency,
        \Magento\Framework\App\ResourceConnection $resource,
        \Magento\MediaStorage\Model\File\UploaderFactory $fileUploaderFactory,
        \Magento\Catalog\Model\ProductFactory $productFactory,
        \Magento\Checkout\Model\Cart $cart,
        \Magetop\Agency\Model\ItemsFactory $itemsFactory,
        \Magetop\Agency\Model\DataFactory $dataFactory,
        \Magetop\Agency\Model\AssociatesFactory $associatesFactory,
        \Magento\Quote\Model\Quote\Item\OptionFactory $quoteOption,
        ItemsCollection $itemsCollectionFactory,
        QuoteCollection $quoteCollectionFactory,
        DataCollection $dataCollectionFactory,
        ProductCollection $productCollectionFactory,
        \Magento\Framework\Registry $coreRegistry,
        \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry,
        TransportBuilder $transportBuilder,
        StateInterface $inlineTranslation,
        \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency,
        \Magento\Framework\Filesystem\Driver\File $fileDriver,
        ConfigurableCollection $configurableCollection,
        \Magento\Catalog\Model\Product\Option $customOptions
    ) {
        $this->_scopeConfig = $context->getScopeConfig();
        $this->_request = $context->getRequest();
        $this->_coreRegistry = $coreRegistry;
        $this->_storeManager = $storeManager;
        $this->_messageManager = $messageManager;
        $this->_customerSession = $customerSession;
        $this->_customer = $customer;
        $this->_filesystem = $filesystem;
        $this->_formKey = $formKey;
        $this->_currency = $currency;
        $this->_resource = $resource;
        $this->_fileUploader = $fileUploaderFactory;
        $this->_product = $productFactory;
        $this->_cart = $cart;
        $this->_items = $itemsFactory;
        $this->_data = $dataFactory;
        $this->_itemsCollection = $itemsCollectionFactory;
        $this->_quoteCollection = $quoteCollectionFactory;
        $this->_dataCollection = $dataCollectionFactory;
        $this->_productCollection = $productCollectionFactory;
        $this->_associates = $associatesFactory;
        $this->_quoteOption = $quoteOption;
        $this->_stockRegistry = $stockRegistry;
        $this->_transportBuilder = $transportBuilder;
        $this->_inlineTranslation = $inlineTranslation;
        $this->_priceCurrency = $priceCurrency;
        $this->_fileDriver = $fileDriver;
        $this->_configurableCollection = $configurableCollection;
        $this->_customOptions = $customOptions;
        parent::__construct($context);
    }

    /**
     * Get Assign Type Setting Config
     *
     * @return bool
     */
    public function getAssignType()
    {
        $config = 'agency/assignproduct/assign';
        return $this->_scopeConfig->getValue($config);
    }

    /**
     * Get Add Approve Product Setting Config
     *
     * @return bool
     */
    public function isAddApprovalRequired()
    {
        $config = 'agency/assignproduct/add_product';
        return $this->_scopeConfig->getValue($config);
    }

    /**
     * Get Edit Approve Product Setting Config
     *
     * @return bool
     */
    public function isEditApprovalRequired()
    {
        $config = 'agency/assignproduct/edit_product';
        return $this->_scopeConfig->getValue($config);
    }

    /**
     * Get Current Customer Id
     *
     * @return int
     */
    public function getCustomerId()
    {
        $customerId = 0;
        if ($this->_customerSession->isLoggedIn()) {
            $customerId = (int) $this->_customerSession->getCustomerId();
        }
        return $customerId;
    }

    /**
     * Check Customer is Logged In or Not
     *
     * @return bool
     */
    public function isLoggedIn()
    {
        if ($this->_customerSession->isLoggedIn()) {
            return true;
        }
        return false;
    }

    /**
     * Get Mediad Path
     *
     * @return string
     */
    public function getMediaPath()
    {
        return $this->_filesystem
                    ->getDirectoryRead(DirectoryList::MEDIA)
                    ->getAbsolutePath();
    }

    /**
     * Get Form Key
     *
     * @return string
     */
    public function getFormKey()
    {
        return $this->_formKey->getFormKey();
    }

    /**
     * Get Assign Product by AssignId
     *
     * @param int $assignId
     *
     * @return object
     */
    public function getAssignProduct($assignId)
    {
        $assignProduct = $this->_items->create()->load($assignId);
        return $assignProduct;
    }

    /**
     * Get Assign Product Collection
     *
     * @return collection object
     */
    public function getCollection()
    {
        $collection = $this->_itemsCollection->create();
        return $collection;
    }

    /**
     * Get Assign Product Quote Items Collection
     *
     * @return collection object
     */
    public function getQuoteCollection()
    {
        $collection = $this->_quoteCollection->create();
        return $collection;
    }

    /**
     * Get Product Collection
     *
     * @return collection object
     */
    public function getProductCollection()
    {
        $collection = $this->_productCollection->create();
        return $collection;
    }

    /**
     * Get Cart
     *
     * @return object
     */
    public function getCart()
    {
        $cartModel = $this->_cart;
        return $cartModel;
    }

    /**
     * Get Current Product Id
     *
     * @return int
     */
    public function getProductId()
    {
        $id = (int) $this->_request->getParam('id');
        return $id;
    }

    /**
     * Get Product
     *
     * @param int $productId [optional]
     *
     * @return object
     */
    public function getProduct($productId = 0)
    {
        if ($productId == 0) {
            $productId = $this->getProductId();
        }
        $product = $this->_product->create()->load($productId);
        return $product;
    }

    /**
     * Get Searched Query String
     *
     * @return string
     */
    public function getQueryString()
    {
        $queryString = $this->_request->getParam('query');
        $queryString = strip_tags(trim($queryString));
        return $queryString;
    }

    /**
     * Check Whether Product Is Valid Or Not.
     *
     * @param int $isAdd [optional]
     *
     * @return bool
     */
    public function checkProduct($isAdd = 0)
    {
        $result = ['msg' => '', '' => 0];
        $assignId = (int) $this->_request->getParam('id');
        if ($assignId == 0) {
            $result[''] = 1;
            $result['msg'] = 'Invalid request.';
            return $result;
        }
        if ($isAdd == 1) {
            $productId = $assignId;
        } else {
            $assignData = $this->getAssignDataByAssignId($assignId);
            $productId = $assignData->getProductId();
        }
        $product = $this->getProduct($productId);
        if ($product->getId() <= 0) {
            $result[''] = 1;
            $result['msg'] = 'Product does not exist.';
            return $result;
        }
        $productType = $product->getTypeId();
        $allowedProductTypes = $this->getAllowedProductTypes();
        if (!in_array($productType, $allowedProductTypes)) {
            $result[''] = 1;
            $result['msg'] = 'Product type not allowed.';
            return $result;
        }
        $customerId = $this->getCustomerId();
        if ($isAdd == 1) {
            $assignId = $this->getAssignId($productId, $customerId);
            if ($assignId > 0) {
                $result[''] = 1;
                $result['msg'] = 'Already assigned to you.';
                return $result;
            }
        }
        return $result;
    }

    /**
     * Return Assign Id by Product Id
     *
     * @param int $productId
     * @param int $agencyId
     *
     * @return int
     */
    public function getAssignId($productId, $agencyId)
    {
        $assignId = 0;
        $collection = $this->getCollection()
                            ->addFieldToFilter('product_id', $productId)
                            ->addFieldToFilter('agency_id', $agencyId);
        foreach ($collection as $item) {
            $assignId = $item->getId();
        }
        return $assignId;
    }

    /**
     * Return Seller Id by Assign Id
     *
     * @param int $assignId
     *
     * @return int
     */
    public function getAssignSellerIdByAssignId($assignId)
    {
        $agencyId = 0;
        $assignProduct = $this->getAssignProduct($assignId);
        if ($assignProduct->getId() > 0) {
            $agencyId = $assignProduct->getAgencyId();
        }
        return $agencyId;
    }

    /**
     * Get Product by Assign Id
     *
     * @param int $assignId
     *
     * @return object
     */
    public function getProductByAssignId($assignId)
    {
        $assignData = $this->getAssignDataByAssignId($assignId);
        $product = $this->getProduct($assignData->getProductId());
        return $product;
    }

    /**
     * Get Assign Data by Assign Id
     *
     * @param int $assignId
     *
     * @return object
     */
    public function getAssignDataByAssignId($assignId)
    {
        $assignProduct = $this->getAssignProduct($assignId);
        return $assignProduct;
    }

    /**
     * Check Whether Assign Product is Valid or Not
     *
     * @param int $assignId
     *
     * @return bool
     */
    public function isValidAssignProduct($assignId)
    {
        $customerId = $this->getCustomerId();
        $collection = $this->getCollection()
                            ->addFieldToFilter('id', $assignId)
                            ->addFieldToFilter('agency_id', $customerId);
        foreach ($collection as $item) {
            if ($item->getId() > 0) {
                return true;
            }
        }

        return false;
    }

    /**
     * Update Stock Data of Product
     *
     * @param int $productId
     * @param int $qty
     * @param int $flag [optional]
     * @param int $oldQty [optional]
     */
    public function updateStockData($productId, $qty, $flag = 0, $oldQty = 0)
    {
        try {
            $product = $this->getProduct($productId);
            $stockItem = $this->_stockRegistry->getStockItem($productId);
            if ($flag == 1) {
                $qty = $qty + $stockItem->getQty() - $oldQty;
            } elseif ($flag == 2) {
                $qty = $stockItem->getQty() - $qty;
            } elseif ($flag == 3) {
                $qty = $qty;
            } else {
                $qty = $qty + $stockItem->getQty();
            }
            $stockItem->setData('qty', $qty);
            $stockItem->save();
        } catch (\Exception $e) {
             $e->getMessage();
        }
    }

    /**
     * Update Price of Product
     *
     * @param int $productId
     * @param float $price
     */
    public function updatePrice($productId, $price)
    {
        $product = $this->getProduct($productId);
        $product->addData(['price' => $price]);
        $product->setId($productId)->save();
    }

    /**
     * Update Stock Data of Product by Assign Id
     *
     * @param int $assignId
     */
    public function updateStockDataByAssignId($assignId)
    {
        $assignData = $this->getAssignDataByAssignId($assignId);
        $productId = $assignData->getProductId();
        $qty = $assignData->getQty();
        $this->updateStockData($productId, $qty, 2);
    }

    /**
     * Update Stock Data of Product by Assign Id
     *
     * @param int $assignId
     */
    public function updateConfigStockDataByAssignId($assignId)
    {
        $model = $this->_associates->create();
        $collection = $model->getCollection()->addFieldToFilter("parent_id", $assignId);
        foreach ($collection as $key => $item) {
            $this->updateStockData($item->getProductId(), $item->getQty(), 2);
            $this->deleteItem($item);
        }
    }

    public function deleteItem($item)
    {
        $item->delete();
    }

    /**
     * Update Assign Product Quote by Assign Id
     *
     * @param int $assignId
     */
    public function updateQuote($assignId)
    {
        $itemIds = [];
        $collection = $this->getQuoteCollection()
                            ->addFieldToFilter('assign_id', $assignId);
        foreach ($collection as $item) {
            $itemIds[] = $item->getItemId();
            $this->deleteItem($item);
        }
        $this->updateCart($itemIds);
    }

    /**
     * Update Cart
     *
     * @param int|array $itemIds
     */
    public function updateCart($itemIds)
    {
        $cartModel = $this->getCart();
        $quote = $cartModel->getQuote();
        foreach ($quote->getAllVisibleItems() as $item) {
            $id = $item->getId();
            if (in_array($id, $itemIds)) {
                $cartModel = $this->removeCartItem($cartModel, $id);
            }
        }
        $cartModel->save();
    }

    public function removeCartItem($cartModel, $id)
    {
        $cartModel->removeItem($id)->save();
        return $cartModel;
    }
    /**
     * Set Updated Price of Product
     */
    public function checkCartPrice()
    {
        $cartModel = $this->getCart();
        $quote = $cartModel->getQuote();
        $this->collectTotals($quote);
        $cartModel->getQuote()->collectTotals()->save();
    }

    /**
     * Assign Product to Seller
     *
     * @param array $data
     * @param int $flag [optional]
     *
     * @return array
     */
    public function assignProduct($data, $flag = 0)
    {
        $result = [
                    'assign_id' => 0,
                    'product_id' => 0,
                    '' => 0,
                    'msg' => '',
                    'qty' => 0,
                    'flag' => 0,
                    'status' => 1,
                    'type' => 0
                ];
        $productId = (int) $data['product_id'];
        $price = (float) $data['price'];
        $description = $data['description'];
        $sellerId = $this->getCustomerId();
        $product = $this->getProduct($productId);
        $type = $product->getTypeId();
        $date = date('Y-m-d');
        $assignProductData = [
                                'product_id' => $productId,
                                'agency_id' => $sellerId,
                                'price' => $price,
                                'description' => $description,
                                'type' => $type,
                                'created_at' => $date,
                                'status' => 1,
                            ];
        $model = $this->_items->create();
        if ($flag == 1) {
            $assignId = $data['assign_id'];
            $assignData = $this->getAssignDataByAssignId($assignId);
            $oldPrice = $assignData->getPrice();
            if ($assignData->getId() > 0) {
                $oldQty = $assignData->getQty();
                $status = $assignData->getStatus();
                $result['old_qty'] = $oldQty;
                $result['prev_status'] = $status;
                $result['flag'] = 1;
                unset($assignProductData['created_at']);
                if ($this->isEditApprovalRequired()) {
                    $result['status'] = 0;
                    $assignProductData['status'] = 0;
                }
            } else {
                return $result;
            }
            $model->addData($assignProductData)->setId($assignId)->save();
            $this->manageDescription($data,$assignId);
        } else {
            if ($this->isAddApprovalRequired()) {
                $result['status'] = 0;
                $assignProductData['status'] = 0;
            }
            $model->setData($assignProductData)->save();
            $this->manageDescription($data, $model->getId());
        }
        if ($model->getId() > 0) {
            $result['product_id'] = $productId;
            $result['assign_id'] = $model->getId();
        }
        return $result;
    }

    /**
     * Process Assigned Product
     *
     * @param array $data
     * @param int $type
     * @param int $flag
     * @return array
     */
    public function processAssignProduct($data, $type, $flag)
    {
        if ($type == "configurable") {
            return $this->assignConfigProduct($data, $flag);
        } else {
            return $this->assignProduct($data, $flag);
        }
    }

    /**
     * Assign Product to Seller
     *
     * @param array $data
     * @param int $flag [optional]
     *
     * @return array
     */
    public function assignConfigProduct($data, $flag = 0)
    {
        $result = [
                    'assign_id' => 0,
                    'product_id' => 0,
                    '' => 0,
                    'msg' => '',
                    'flag' => 0,
                    'status' => 1,
                    'type' => 1,
                    'associates' => ''
                ];
        $productId = (int) $data['product_id'];
        $description = $data['description'];
        $sellerId = $this->getCustomerId();
        $type = "configurable";
        $date = date('Y-m-d');
        $price = 0;
        $assignProductData = [
                                'product_id' => $productId,
                                'agency_id' => $sellerId,
                                'price' => 0,
                                'description' => $description,
                                'type' => $type,
                                'created_at' => $date,
                                'status' => 1,
                            ];
        $model = $this->_items->create();
        if ($flag == 1) {
            $assignId = $data['assign_id'];
            $assignData = $this->getAssignDataByAssignId($assignId);
            if ($assignData->getId() > 0) {
                $status = $assignData->getStatus();
                $result['prev_status'] = $status;
                $result['flag'] = 1;
                unset($assignProductData['created_at']);
                if ($this->isEditApprovalRequired()) {
                    $result['status'] = 0;
                    $assignProductData['status'] = 0;
                }
            } else {
                return $result;
            }
            $model->addData($assignProductData)->setId($assignId)->save();
            $this->manageDescription($data,$assignId);
        } else {
            if ($this->isAddApprovalRequired()) {
                $result['status'] = 0;
                $assignProductData['status'] = 0;
            }
            $model->setData($assignProductData)->save();
            $this->manageDescription($data,$model->getId());
        }
        if ($model->getId() > 0) {
            $result['product_id'] = $productId;
            $result['assign_id'] = $model->getId();
            $result['associates'] = $this->setAssociatedOptions($data, $model->getId(), $productId);
        }
        return $result;
    }

    /**
     * Set Associated Product Data
     *
     * @param array $data
     * @param int $parentId
     * @param int $parentProductId
     * @return array
     */
    public function setAssociatedOptions($data, $parentId, $parentProductId)
    {
        if ($this->isAddApprovalRequired()) {
            $status = 0;
        } else {
            $status = 1;
        }
        $result = [];
        foreach ($data['products'] as $productId => $info) {
            if (array_key_exists("id", $info)) {
                $options = "";
                $price = $info['price'];
                $item = [];
                $item['product_id'] = $productId;
                $item['parent_id'] = $parentId;
                $item['parent_product_id'] = $parentProductId;
                $item['options'] = $options;
                $item['price'] = $price;
                if (array_key_exists("associate_id", $info)) { //edit product case
                    $associate = $this->getAssociatedItem($info['associate_id']);
                    $oldPrice = $associate->getPrice();
                    $this->updateRecord($associate, $item, $info['associate_id']);
                } else {
                    $this->newRecord($this->_associates->create(), $item);
                }
            }
        }
        return $result;
    }

    public function updateRecord($model, $data, $id)
    {
        return $model->addData($data)->setId($id)->save();
    }

    public function newRecord($model, $data)
    {
        return $model->setData($data)->save();
    }

    public function getAssociatedItem($associateId)
    {
        return $this->_associates->create()->load($associateId);
    }
    /**
     * Dissapprove Assign Product
     *
     * @param int $assignId
     * @param int $status [optional]
     * @param int $flag [optional]
     */
    public function disApproveProduct($assignId, $status = 0, $flag = 0, $qty = 0)
    {
        $assignProduct = $this->getAssignProduct($assignId);
        if ($assignProduct->getId() > 0) {
            if ($status == 1) {
                $productId = $assignProduct->getProductId();
                $data = [];
                $data['status'] = 0;
                $data['agency_id'] = $assignProduct->getAgencyId();
                $data['product_id'] = $assignProduct->getProductId();
                $assignProduct->setData($data)->setId($assignId)->save();
            }
        }
        return $assignProduct;
    }

    /**
     * Dissapprove Assign Product
     *
     * @param int $assignId
     * @param int $status [optional]
     * @param int $flag [optional]
     */
    public function disApproveConfigProduct($data, $status = 0, $byAdmin = false)
    {
        if (!$byAdmin) {
            $assignId = $data['assign_id'];
        } else {
            $assignId = $data;
        }
        $assignProduct = $this->getAssignProduct($assignId);
        if ($assignProduct->getId() > 0) {
            if ($status == 1) {
                $parentProductId = $assignProduct->getProductId();
                $prodata = [];
                $prodata['status'] = 0;
                $prodata['agency_id'] = $assignProduct->getAgencyId();
                $prodata['product_id'] = $assignProduct->getProductId();
                $assignProduct->setData($prodata)->setId($assignId)->save();
            }
        }
        return $assignProduct;
    }

    /**
     * Approve Assign Product
     *
     * @param int $assignId
     */
    public function approveProduct($assignId)
    {
        $assignProduct = $this->getAssignProduct($assignId);
        if ($assignProduct->getId() > 0) {
            $status = $assignProduct->getStatus();
            if ($status == 0) {
                $productId = $assignProduct->getProductId();
                $data = [];
                $data['status'] = 1;
                $data['agency_id'] = $assignProduct->getAgencyId();
                $data['product_id'] = $assignProduct->getProductId();
                $assignProduct->setData($data)->setId($assignId)->save();
            }
        }
        return $assignProduct;
    }

    /**
     * Approve Assign Product
     *
     * @param int $assignId
     */
    public function approveConfigProduct($assignId)
    {
        $assignProduct = $this->getAssignProduct($assignId);
        if ($assignProduct->getId() > 0) {
            $status = $assignProduct->getStatus();
            if ($status == 0) {
                $productId = $assignProduct->getProductId();
                $data = [];
                $data['status'] = 1;
                $data['agency_id'] = $assignProduct->getAgencyId();
                $data['product_id'] = $assignProduct->getProductId();
                $assignProduct->setData($data)->setId($assignId)->save();
                $model = $this->_associates->create();
                $collection = $model->getCollection()->addFieldToFilter("parent_id", $assignId);
            }
        }
        return $assignProduct;
    }

    /**
     * Get Assign Products
     *
     * @param int $productId
     * @param string $sort [optional]
     * @param string $order [optional]
     *
     * @return collection object
     */
    public function getAssignProducts($productId, $sort = '', $order = 'ASC', $exclude = true)
    {
        $collection = $this->getCollection();
        $collection->addFieldToFilter('product_id', $productId);
        if ($sort != '') {
            $collection->setOrder($sort, $order);
        }
        return $collection;
    }

    /**
     * Get All Product Details Including Assign Products
     *
     * @param int $productId
     * @param int $mode [optional]
     * @param string $sort [optional]
     * @param string $order [optional]
     *
     * @return array
     */
    public function getTotalProducts($productId, $mode = 0, $sort = '', $order = 'ASC')
    {
        $totalProducts = [];
        $collection = $this->getAssignProducts($productId, $sort, $order);
        foreach ($collection as $assignProduct) {
            $productData = [];
            $productData['description'] = $assignProduct->getDescription();
            $productData['price'] = (float) $assignProduct->getPrice();
            $productData['assign_id'] = $assignProduct->getId();
            $productData['agency_id'] = $assignProduct->getAgencyId();
            $productData['condition'] = $assignProduct->getCondition();
            $totalProducts[] = $productData;
        }
        
        if ($mode == 0) {
            $product = $this->getProduct($productId);
            if ($product->getId()) {
                $productData = [];
                $productData['description'] = $product->getDescription();
                $productData['price'] = (float) $product->getFinalPrice();
                $productData['assign_id'] = 0;
                $productData['agency_id'] = 0;
                $totalProducts[] = $productData;
            }
        }
        return $totalProducts;
    }

    /**
     * Get All Assign Product Details Excluding Main Product
     *
     * @param int $productId
     *
     * @return array
     */
    public function getAllAssignedProducts($productId)
    {
        $totalProducts = $this->getTotalProducts($productId, 1);
        return $totalProducts;
    }

    /**
     * Get Minimum Price with Currency
     *
     * @param int $productId
     *
     * @return string
     */
    public function getMinimumPriceHtml($productId, $type = '-')
    {
        $prices = [];
        if ($type == "configurable") {
            $model = $this->_associates->create();
            $collection = $model->getCollection()->addFieldToFilter("parent_product_id", $productId);
            foreach ($collection as $key => $item) {
                $prices[$key] = $item->getPrice();
            }
        } else {
            $totalProducts = $this->getTotalProducts($productId);
            foreach ($totalProducts as $key => $product) {
                $prices[$key] = $product['price'];
            }
        }
        sort($prices);
        $price = $prices[0];
        return $this->_currency->currency($price, true, false);
    }

    /**
     * Get Sorting Order Info
     *
     * @return array
     */
    public function getSortingOrderInfo()
    {
        $assignType = $this->getAssignType();
        if ($assignType == 1) {
            $result = ['sort_by' => 'price', 'order_type' => 'DESC'];
        } else {
            $result = ['sort_by' => 'price', 'order_type' => 'ASC'];
        }
        return $result;
    }

    /**
     * Assign Product to Seller By Product Id
     *
     * @param int $productId
     */
    public function assignAgency($productId)
    {
        if ($this->hasAssignedProducts($productId)) {
            $price = 0;
            $assignId = 0;
            $agencyId = 0;
            $sortingInfo = $this->getSortingOrderInfo();
            $sortBy = $sortingInfo['sort_by'];
            $orderType = $sortingInfo['order_type'];
            $assignProducts = $this->getTotalProducts($productId, 1, $sortBy, $orderType);
            foreach ($assignProducts as $key => $product) {
                $assignId = $product['assign_id'];
                $agencyId = $product['agency_id'];
                $price = $product['price'];
                break;
            }
            $this->updatePrice($productId, $price);
            $assignProduct = $this->getAssignProduct($assignId);
            $assignProduct->delete();
        }
    }
    /**
     * Remove All Pending Assign Product If Main Product Does Not Exist
     *
     * @param int $productId
     */
    public function removeAssignProducts($productId)
    {
        $product = $this->getProduct($productId);
        if (!$product->getId()) {
            $assignId = 0;
            $collection = $this->getCollection()
                                ->addFieldToFilter('product_id', $productId);
            foreach ($collection as $item) {
                $this->removeAssignProduct($item);
            }
        }
    }

    /**
     * Remove Assign Product If Main Product Does Not Exist
     *
     * @param int $productId
     */
    public function removeAssignProduct($product)
    {
        $product->delete();
    }

    /**
     * Check Whether Product Has Assigned Product Or Not
     *
     * @param int $productId [optional]
     *
     * @return bool
     */
    public function hasAssignedProducts($productId = 0)
    {
        $assignProductCollection = $this->getAssignProducts($productId);
        if ($assignProductCollection->getSize()) {
            return true;
        }

        return false;
    }

    /**
     * Check Whether Added Product to Cart is New or Not
     *
     * @return bool
     */
    public function isNewProduct($productId = 0, $assignId = 0, $childAssignId = 0)
    {
        if ($productId == 0) {
            $productId = (int) $this->_request->getParam('product');
        }
        if ($assignId == 0) {
            $assignId = (int) $this->_request->getParam('assignproduct_id');
        }
        if ($childAssignId == 0) {
            $childAssignId = (int) $this->_request->getParam('associate_id');
        }
        $cartModel = $this->getCart();
        $quoteId = $cartModel->getQuote()->getId();
        $collection = $this->getQuoteCollection()
                            ->addFieldToFilter('product_id', $productId)
                            ->addFieldToFilter('assign_id', $assignId)
                            ->addFieldToFilter('child_assign_id', $childAssignId)
                            ->addFieldToFilter('quote_id', $quoteId);
        foreach ($collection as $item) {
            if ($item->getId() > 0) {
                return false;
            }
        }
        return true;
    }

    /**
     * Get Quote Item Id to Add Quantity to Existing Item In Cart According to Seller
     *
     * @param int $assignId
     * @param int $productId
     * @param int $quoteId
     *
     * @return int
     */
    public function getRequestedItemId($assignId, $productId, $quoteId)
    {
        $itemId = 0;
        $collection = $this->getQuoteCollection()
                            ->addFieldToFilter('assign_id', $assignId)
                            ->addFieldToFilter('product_id', $productId)
                            ->addFieldToFilter('quote_id', $quoteId);
        foreach ($collection as $item) {
            $itemId = $item->getItemId();
            break;
        }
        return $itemId;
    }

    /**
     * Get Price of Assign Product by Assign Id
     *
     * @param int $assignId
     *
     * @return float
     */
    public function getAssignProductPrice($assignId)
    {
        $price = 0;
        $assignProduct = $this->getAssignProduct($assignId);
        if ($assignProduct->getId() > 0) {
            $price = $assignProduct->getPrice();
        }
        return $price;
    }

    /**
     * Get Assign Data by Quote Item Id
     *
     * @param int $itemId
     *
     * @return array
     */
    public function getAssignDataByItemId($itemId)
    {
        $assignData = ['assign_id' => 0];
        $collection = $this->getQuoteCollection()
                            ->addFieldToFilter('item_id', $itemId);
        foreach ($collection as $item) {
            $assignData['agency_id'] = $item->getAgencyId();
            $assignData['assign_id'] = $item->getAssignId();
            $assignData['child_assign_id'] = $item->getChildAssignId();
            break;
        }
        return $assignData;
    }

    /**
     * Check Whether Quantity is Allowed from Seller or Not
     *
     * @param int $qty
     * @param int $productId
     * @param int $assignId
     *
     * @return bool
     */
    public function isQtyAllowed($qty, $productId, $assignId)
    {
        $product = $this->getProduct($productId);
        $productType = $product->getTypeId();
        $allowedProductTypes = $this->getAllowedProductTypes();
        if (!in_array($productType, $allowedProductTypes)) {
            return true;
        }
        $totalQty = 0;
        if ($assignId == 0) {
            $stockItem = $this->_stockRegistry->getStockItem($productId);
            $totalQty = $stockItem->getQty();
            $collection = $this->getCollection()
                            ->addFieldToFilter('product_id', $productId);
            foreach ($collection as $item) {
                $totalQty = $totalQty - (int) $item->getQty();
            }
        } else {
            $assignProduct = $this->getAssignProduct($assignId);
            if ($assignProduct->getId() > 0) {
                $totalQty = (int) $assignProduct->getQty();
            }
        }
        $inCartQty = $this->inCartQty($productId, $assignId);
        $totalQty = $totalQty - $inCartQty;
        if ($totalQty >= $qty) {
            return true;
        }
        return false;
    }

    public function getValueFromArray($array, $key, $defaultValue = 0)
    {
        $value = $defaultValue;
        if (array_key_exists($key, $array)) {
            $value = $array[$key];
        }
        return $value;
    }

    /**
     * Check Whether Quantity is Allowed from Seller or Not
     *
     * @param int $qty
     * @param int $productId
     * @param int $assignId
     *
     * @return bool
     */
    public function isConfigQtyAllowed($info, $product)
    {
        $productType = $product->getTypeId();
        $allowedProductTypes = $this->getAllowedProductTypes();
        if (!in_array($productType, $allowedProductTypes)) {
            return true;
        }
        $assignId = 0;
        $childAssignId = 0;
        $qty = 1;
        $productId = $product->getId();
        if (is_array($info)) {
            $assignId = $this->getValueFromArray($info, 'assignproduct_id');
            $childAssignId = $this->getValueFromArray($info, 'associate_id');
            $qty = $this->getValueFromArray($info, 'qty', 1);
        }
        if ($assignId == 0) {
            if (!$this->hasAssignedProducts($productId)) {
                return true;
            }
            $childProductId = 0;
            if (array_key_exists("selected_configurable_option", $info)) {
                $childProductId = $info['selected_configurable_option'];
                $totalQty = $this->getTotalQty($childProductId, $productId);
            }
        } else {
            $assignProduct = $this->_associates->create()->load($childAssignId);
            if ($assignProduct->getId() > 0) {
                $totalQty = (int) $assignProduct->getQty();
            }
        }

        $inCartQty = $this->inCartQty($productId, $assignId, $childAssignId);
        $totalQty = $totalQty - $inCartQty;
        if ($totalQty >= $qty) {
            return true;
        }
        return false;
    }

    public function getTotalQty($childProductId, $productId)
    {
        $stockItem = $this->_stockRegistry->getStockItem($childProductId);
        $totalQty = $stockItem->getQty();
        $collecton = $this->_itemsCollection
                        ->create()
                        ->addFieldToFilter("product_id", $productId)
                        ->addFieldToFilter("status", 1);
        if ($collecton->getSize()) {
            $allIds = [];
            foreach ($collecton as $item) {
                $allIds[] = $item->getId();
            }
            $collection = $this->_associates
                        ->create()
                        ->getCollection()
                        ->addFieldToFilter('parent_id', ["in" => $allIds])
                        ->addFieldToFilter('product_id', $childProductId);
        } else {
            $collection = $this->_associates
                        ->create()
                        ->getCollection()
                        ->addFieldToFilter('product_id', $childProductId);
        }
        foreach ($collection as $item) {
            $totalQty = $totalQty - (int) $item->getQty();
        }
        return $totalQty;
    }

    /**
     * Get Quantity Present in Cart
     *
     * @param int $productId
     * @param int $assignId
     *
     * @return int
     */
    public function inCartQty($productId, $assignId, $childAssignId = 0)
    {
        $qty = 0;
        $cartModel = $this->getCart();
        $quoteId = $cartModel->getQuote()->getId();
        if ($childAssignId > 0) {
            $collection = $this->getQuoteCollection()
                            ->addFieldToFilter('product_id', $productId)
                            ->addFieldToFilter('assign_id', $assignId)
                            ->addFieldToFilter('child_assign_id', $childAssignId)
                            ->addFieldToFilter('quote_id', $quoteId);
        } else {
            $collection = $this->getQuoteCollection()
                            ->addFieldToFilter('product_id', $productId)
                            ->addFieldToFilter('assign_id', $assignId)
                            ->addFieldToFilter('quote_id', $quoteId);
        }
        
        foreach ($collection as $item) {
            $qty = $item->getQty();
        }
        return $qty;
    }

    /**
     * Get Full Action Name
     *
     * @return string
     */
    public function getFullActionName()
    {
        return $this->_request->getFullActionName();
    }

    /**
     * Check Whether Customer Is $agencyId Or Not
     *
     * @param int $agencyId [Optional]
     *
     * @return bool
     */
    public function isAgency($agencyId = '')
    {
        if ($agencyId == '') {
            $agencyId = $this->getCustomerId();
        }
		$customer = $this->_customer->create()->load($agencyId);
		if($customer->getGroupId()==3){
			return true;
		}
        return false;
    }

    /**
     * Get Image Url for Assign Product
     *
     * @param string $image
     *
     * @return string
     */
    public function getImageUrl($image)
    {
        $currentStore = $this->_storeManager->getStore();
        $mediaUrl = $currentStore->getBaseUrl(UrlInterface::URL_TYPE_MEDIA);
        $imageUrl = $mediaUrl.'agency/assignproduct/product/'.$image;
        return $imageUrl;
    }
    
    /**
     * Get First Object From Collection
     *
     * @param array | int | string $value
     * @param array | string $field
     * @param object $collection
     *
     * @return $object
     */
    public function getDataByField($values, $fields, $collection)
    {
        $item = false;
        if (is_array($values)) {
            foreach ($values as $key => $value) {
                $field = $fields[$key];
                $collection = $collection->addFieldToFilter($field, $value);
            }
        } else {
            $collection = $collection->addFieldToFilter($fields, $values);
        }
        foreach ($collection as $item) {
            return $item;
        }
        return $item;
    }

    /**
     * Remove Unnecessasy Assocaited Assigned Products
     *
     * @param array $result
     */
    public function processConfigProduct($result)
    {
        $productIds = [];
        $assignId = $result['assign_id'];
        foreach ($result['associates'] as $productId => $info) {
            $productIds[] = $productId;
        }
        $model = $this->_associates->create();
        $collection = $model->getCollection()->addFieldToFilter("parent_id", $assignId);
        foreach ($collection as $key => $item) {
            if (!in_array($item->getProductId(), $productIds)) {
                $this->updateStockData($item->getProductId(), $item->getQty(), 2);
                $this->deleteItem($item);
            }
        }
    }

    /**
     * Manage Assigned Products Price
     *
     * @param object $quote
     */
    public function collectTotals($quote)
    {
        foreach ($quote->getAllVisibleItems() as $item) {
            $itemId = $item->getId();
            $assignData = $this->getAssignDataByItemId($itemId);
            if ($assignData['assign_id'] > 0) {
                $assignId = $assignData['assign_id'];
                if ($assignData['child_assign_id'] > 0) {
                    $childAssignId = $assignData['child_assign_id'];
                    $price = $this->getAssocitePrice($assignId, $childAssignId);
                } else {
                    $price = $this->getAssignProductPrice($assignId);
                }
                $price = $this->getFinalPrice($price);
                $item->setCustomPrice($price);
                $item->setOriginalCustomPrice($price);
                $item->setRowTotal($item->getQty()*$price);
                $item->getProduct()->setIsSuperMode(true);
            }
        }
    }

    /**
     * Get Associated Assigned Product Price
     *
     * @param int $assignId
     * @param int $childAssignId
     * @return float
     */
    public function getAssocitePrice($assignId, $childAssignId)
    {
        $price = 0;
        $model = $this->_associates->create();
        $collection = $model->getCollection()
                            ->addFieldToFilter("parent_id", $assignId)
                            ->addFieldToFilter("id", $childAssignId);
        foreach ($collection as $item) {
            $price = $item->getPrice();
        }
        return $price;
    }

    /**
     * Get Associated Assigned Product Quantity
     *
     * @param int $assignId
     * @param int $childAssignId
     * @return int
     */
    public function getAssociteQty($assignId, $childAssignId)
    {
        $qty = 0;
        $model = $this->_associates->create();
        $collection = $model->getCollection()
                            ->addFieldToFilter("parent_id", $assignId)
                            ->addFieldToFilter("id", $childAssignId);
        foreach ($collection as $item) {
            $qty = $item->getQty();
        }
        return $qty;
    }

    /**
     * Validate Data
     *
     * @param array $data
     * @return array
     */
    public function validateData($data, $type)
    {
        if ($type == "configurable") {
            return $this->validateConfigData($data);
        }
        $result = ['' => false, 'msg' => ''];
        $msg = "";
        try {
            if (trim($data['price']) == "") {
                $msg .= "Price is required field.";
                $result[''] = true;
            } else {
                if (!is_numeric(trim($data['price']))) {
                    $msg .= "Price should be numeric.";
                    $result[''] = true;
                }
            }
            if (trim($data['description']) == "") {
                $msg .= "Description is required field.";
                $result[''] = true;
            }
            $result['msg'] = $msg;
        } catch (\Exception $e) {
            $result[''] = true;
            $result['msg'] = "Something went wrong.";
        }
        return $result;
    }

    /**
     * Validate Price
     *
     * @param int $price
     * @return array
     */
    public function validatePrice($price)
    {
        $result = ["" => false, "msg" => ""];
        $msg = "";
        if (trim($price) == "") {
            $msg = "Price is required field.";
            $result[''] = true;
        } else {
            if (!is_numeric(trim($price))) {
                $msg = "Price should be numeric.";
                $result[''] = true;
            }
        }
        $result['msg'] = $msg;
        return $result;
    }

    /**
     * Validate Quantity
     *
     * @param int $qty
     * @return array
     */
    public function validateQty($qty)
    {
        $result = ["" => false, "msg" => ""];
        $msg = "";
        if (trim($qty) == "") {
            $msg = "Quantity is required field.";
            $result[''] = true;
        } else {
            if (!is_numeric(trim($qty))) {
                $msg = "Quantity should be numeric.";
                $result[''] = true;
            }
        }
        $result['msg'] = $msg;
        return $result;
    }

    /**
     * Validate Data
     *
     * @param array $data
     * @return array
     */
    public function validateConfigData($data)
    {
        $result = ['' => false, 'msg' => ''];
        $msg = "";
        try {
            if (trim($data['description']) == "") {
                $msg .= "Description is required field.";
                $result[''] = true;
            }
            $count = 0;
            foreach ($data['products'] as $productId => $info) {
                if (array_key_exists("id", $info)) {
                    $validateQty = $this->validateQty($info['qty']);
                    $validatePrice = $this->validatePrice($info['price']);
                    if ($validateQty['']) {
                        $msg .= $validateQty['msg'];
                        $result[''] = true;
                        $result['msg'] = $msg;
                        return $result;
                    }
                    if ($validatePrice['']) {
                        $msg .= $validatePrice['msg'];
                        $result[''] = true;
                        $result['msg'] = $msg;
                        return $result;
                    }
                    $count++;
                }
            }
            if ($count == 0) {
                $msg .= "Please select associated products.";
                $result[''] = true;
            }
            $result['msg'] = $msg;
        } catch (\Exception $e) {
            $result[''] = true;
            $result['msg'] = "Something went wrong.";
        }
        return $result;
    }

    /**
     * Get Associated Product Collection
     *
     * @param int $productId
     * @return object
     */
    public function getAssignProductCollection($productId,$agencyId=null)
    {
        $collection = $this->_itemsCollection->create();
        $collection->addFieldToFilter("product_id", $productId);
        if($agencyId > 0 ){
			$collection->addFieldToFilter("agency_id", $agencyId);
		}
		return $collection;
    }

    /**
     * Get Allowed Product Types
     *
     * @return array
     */
    public function getAllowedProductTypes()
    {
        return $this->_allowedProductTypes;
    }

    /**
     * Get Associates Data
     *
     * @param int $assignId
     * @return array
     */
    public function getAssociatesData($assignId)
    {
        $result = [];
        $model = $this->_associates->create();
        $collection = $model->getCollection()->addFieldToFilter("parent_id", $assignId);
        foreach ($collection as $item) {
            $info = [
                    'id' => $item->getId(),
                    'qty' => $item->getQty(),
                    'price' => number_format($item->getPrice(), 2)
                ];
            $result[$item->getProductId()] = $info;
        }
        return $result;
    }

    /**
     * Get Associated Options of Assign Product
     *
     * @param int $productId
     * @return array
     */
    public function getAssociatedOptions($productId)
    {
        $result = [];
        $model = $this->_associates->create();
        $collection = $model->getCollection()->addFieldToFilter("parent_product_id", $productId);
        foreach ($collection as $item) {
            $info = [
                    'id' => $item->getId(),
                    'qty' => $item->getQty(),
                    'price' => number_format($this->convertPriceFromBase($item->getPrice()), 2)
                ];
            $result[$item->getProductId()][$item->getParentId()] = $info;
        }
        return $result;
    }

    /**
     * Get Currenct Currency Symbol
     *
     * @return string
     */
    public function getCurrencySymbol()
    {
        return $this->_storeManager->getStore()->getCurrentCurrencyCode();
    }

    /**
     * Get Admin Email Id.
     *
     * @return string
     */
    public function getAdminEmail()
    {
        $config = 'agency/assignproduct/admin_email';
        return $this->_scopeConfig->getValue($config);
    }

    /**
     * Get Admin Email Name.
     *
     * @return string
     */
    public function getAdminName()
    {
        $config = 'agency/assignproduct/admin_name';
        return $this->_scopeConfig->getValue($config);
    }

    /**
     * Get Product Edit Message.
     *
     * @return string
     */
    public function getEditProductMessage()
    {
        $config = 'agency/assignproduct/edit_msg';
        return $this->_scopeConfig->getValue($config);
    }

    /**
     * Get Product Add Message.
     *
     * @return string
     */
    public function getAddProductMessage()
    {
        $config = 'agency/assignproduct/add_msg';
        return $this->_scopeConfig->getValue($config);
    }

    /**
     * Send Product Email
     *
     * @param array $data
     * @param booln $isEdit
     */
    public function sendProductMail($data, $isEdit = false)
    {
        try {
            $customer = $this->_customerSession->getCustomer();
            $adminEmail = $this->getAdminEmail();
            $adminName = $this->getAdminName();
            if ($adminEmail != '') {
                $area = Area::AREA_FRONTEND;
                $store = $this->_storeManager->getStore()->getId();
                $product = $this->getProduct($data['product_id']);
                $productName = $product->getName();
                $templateId = "product_template";
                if ($isEdit) {
                    $msg = $this->getEditProductMessage();
                } else {
                    $msg = $this->getAddProductMessage();
                }
                $templateOptions = ['area' => $area, 'store' => $store];
                $templateVars = [
                                    'store' => $this->_storeManager->getStore(),
                                    'message' => $msg,
                                    'admin_name' => $adminName,
                                    'seller_name' => $shopTitle,
                                    'product_name' => $productName,
                                    'msg' => $msg,
                                ];
                $from = ['email' => $customer->getEmail(), 'name' => $shopTitle];
                $this->_inlineTranslation->suspend();
                $to = [$adminEmail];
                $transport = $this->_transportBuilder
                                    ->setTemplateIdentifier($templateId)
                                    ->setTemplateOptions($templateOptions)
                                    ->setTemplateVars($templateVars)
                                    ->setFrom($from)
                                    ->addTo($to)
                                    ->getTransport();
                $transport->sendMessage();
                $this->_inlineTranslation->resume();
            }
        } catch (\Excecption $e) {
            $error = $e->getMessage();
        }
    }

    public function sendStatusMail($assignProduct, $flag = 0)
    {
        try {
            $adminEmail = $this->getAdminEmail();
            $adminName = $this->getAdminName();
            if ($adminEmail != '') {
                if ($assignProduct->getId() <= 0) {
                    return;
                }
                $agencyId = $assignProduct->getAgencyId();
                $product = $this->getProduct($assignProduct->getProductId());
                $customer = $this->_customer->create()->load($agencyId);
                $sellerName = $customer->getFirstname();
                $area = Area::AREA_FRONTEND;
                $store = $this->_storeManager->getStore()->getId();
                $productName = $product->getName();
                if ($flag == 0) {
                    $templateId = "product_approve";
                    $msg = __("Your assigned product for '%1' is approved.", $productName);
                } else {
                    $templateId = "product_disapprove";
                    $msg = __("Your assigned product for '%1' is disapproved.", $productName);
                }
                $templateOptions = ['area' => $area, 'store' => $store];
                $templateVars = [
                                    'store' => $this->_storeManager->getStore(),
                                    'seller_name' => $sellerName,
                                    'msg' => $msg,
                                ];
                $from = ['email' => $adminEmail, 'name' => $adminName];
                $this->_inlineTranslation->suspend();
                $to = [$customer->getEmail()];
                $transport = $this->_transportBuilder
                                    ->setTemplateIdentifier($templateId)
                                    ->setTemplateOptions($templateOptions)
                                    ->setTemplateVars($templateVars)
                                    ->setFrom($from)
                                    ->addTo($to)
                                    ->getTransport();
                $transport->sendMessage();
                $this->_inlineTranslation->resume();
            }
        } catch (\Excecption $e) {
            $error = $e->getMessage();
        }
    }

    public function getProductFromItemId($quoteItemId)
    {
        $productId = 0;
        $item = $this->_quoteOption
                    ->create()
                    ->getCollection()
                    ->addFieldToFilter("item_id", $quoteItemId)
                    ->addFieldToFilter("code", "simple_product")
                    ->getFirstItem();
        if ($item) {
            $productId = $item->getProductId();
        }
        return $productId;
    }

    public function getImagesCollection($assignId)
    {
        $collection = $this->_dataCollection->create();
        $collection->addFieldToFilter('type', 1);
        $collection->addFieldToFilter("assign_id", $assignId);
        return $collection;
    }

    public function manageImages($data, $result)
    {
        $data = $data;
        $totalImages = (int) $this->_request->getParam('total');
        $baseImage = (int) $this->_request->getParam('base_image');
        $deletedImages = trim($this->_request->getParam('delete_ids'));
        $assignId = $result['assign_id'];
        $this->uploadImages($totalImages, $assignId);
        $this->deleteImages($deletedImages, $assignId);
        $this->setBaseImage($baseImage, $assignId);
    }

    public function setBaseImage($baseImage, $assignId)
    {
        $store_id = $this->_storeManager->getStore()->getStoreId();
        $update = true;
        if ($baseImage == 0) {
            $old_base = $this->_dataCollection->create()
                        ->addFieldToFilter("type", 1)
                        ->addFieldToFilter("is_default", 1)
                        ->addFieldToFilter("assign_id", $assignId)
                        ->addFieldToFilter("store_view", $store_id);
            if ($old_base->getSize()) {
                foreach($old_base as $key) {
                    $key->setIsDefault(0)->save();
                }
            }
            return;
        }
        try {
            $collection = $this->_dataCollection->create();
            $collection->addFieldToFilter("type", 1);
            $collection->addFieldToFilter("assign_id", $assignId);
            $collection->setPageSize($baseImage)->setCurPage(1);
            $item = $collection->getLastItem();
            $baseImageId = $item->getId();
            $old_base = $this->_dataCollection->create()
                        ->addFieldToFilter("type", 1)
                        ->addFieldToFilter("is_default", 1)
                        ->addFieldToFilter("assign_id", $assignId)
                        ->addFieldToFilter("store_view", ['eq' => $store_id]);
            if ($old_base->getSize()) {
                foreach($old_base as $key) {
                    if ($baseImageId != $key->getId()) {
                        $key->setIsDefault(0)->save();
                    } else {
                        $update = false;
                    }
                }
            }
            if ($update) {
                $data = [];
                $data['is_default'] = 1;
                $data['store_view'] = $store_id;
                $collection = $this->_data->create()->load($baseImageId);
                $collection->addData($data)->setId($baseImageId)->save();
            }
        } catch (\Exception $e) {
            $e->getMessage();
        }
    }
    public function getCurrencyCode()
    {
        return $this->_storeManager->getStore()->getCurrentCurrency()->getCode();
    }

    public function convertPriceFromBase($amount)
    {
        $currency = null;
        $store = $this->_storeManager->getStore()->getStoreId();
        $rate = $this->_priceCurrency->convert($amount, $store, $currency);
        return $this->_priceCurrency->round($rate);
    }

    public function convertPriceToBase($amount)
    {
        $currency = null;
        $store = $this->_storeManager->getStore()->getStoreId();
        $rate = $this->_priceCurrency->convert($amount, $store, $currency);
        $amount = $amount / $rate;
        return $this->_priceCurrency->round($amount);
    }

    public function getFinalPrice($price)
    {
        $baseCurrencyCode = $this->getBaseCurrencyCode();
        $currentCurrencyCode = $this->getCurrentCurrencyCode();
        if ($baseCurrencyCode !== $currentCurrencyCode) {
            return $this->convertPriceFromBase($price);
        }
        return $price;
    }

    /**
     * Get store base currency code
     *
     * @return string
     */
    public function getBaseCurrencyCode()
    {
        return $this->_storeManager->getStore()->getBaseCurrencyCode();
    }
    
    /**
     * Get current store currency code
     *
     * @return string
     */
    public function getCurrentCurrencyCode()
    {
        return $this->_storeManager->getStore()->getCurrentCurrencyCode();
    }
    
    /**
     * Get default store currency code
     *
     * @return string
     */
    public function getDefaultCurrencyCode()
    {
        return $this->_storeManager->getStore()->getDefaultCurrencyCode();
    }

    /**
     * Get allowed store currency codes
     *
     * If base currency is not allowed in current website config scope,
     * then it can be disabled with $skipBaseNotAllowed
     *
     * @param bool $skipBaseNotAllowed
     * @return array
     */
    public function getAvailableCurrencyCodes($skipBaseNotAllowed = false)
    {
        return $this->_storeManager->getStore()->getAvailableCurrencyCodes($skipBaseNotAllowed);
    }
    
    /**
     * Get array of installed currencies for the scope
     *
     * @return array
     */
    public function getAllowedCurrencies()
    {
        return $this->_storeManager->getStore()->getAllowedCurrencies();
    }
    
    /**
     * Get current currency rate
     *
     * @return float
     */
    public function getCurrentCurrencyRate()
    {
        return $this->_storeManager->getStore()->getCurrentCurrencyRate();
    }
    
    /**
     * Get currency symbol for current locale and currency code
     *
     * @return string
     */
    public function getCurrentCurrencySymbol()
    {
        return $this->_priceCurrency->getCurrencySymbol();
    }

    public function getBaseMediaUrl()
    {
        $currentStore = $this->_storeManager->getStore();
        return $currentStore->getBaseUrl(UrlInterface::URL_TYPE_MEDIA);
    }

    public function getAssignedAssociatedProducts($assignId)
    {
        $collection = $this->_productCollection->create()->addAttributeToSelect("name");

        $joinTable = $this->_resource
                        ->getTableName('agency_assignproduct_associated_products');
        $sql = 'maas.product_id = e.entity_id';
        $sql .= ' and maas.parent_id = '.$assignId;
        $fields = ['qty', 'price', 'product_id'];
        $collection->getSelect()->join($joinTable.' as maas', $sql, $fields);
        return $collection;
    }

    public function getCurrentProduct()
    {
        return $this->_coreRegistry->registry("current_product");
    }

    public function isEnabled($assignId)
    {
        $model = $this->_items->create()->load($assignId);
        return $model->getStatus();
    }

    public function getCustomer($customerId)
    {
        return $this->_customer->create()->load($customerId);
    }
    /**
     * getAssocatedProductQty function
     *
     * @param [int] $productId
     * @return qty
     */
    public function getAssocatedProductQty($productId)
    {
        $qty = 0;
        $collection = $this->getCollection();
        $joinTable = $this->_resource
                        ->getTableName('agency_assignproduct_associated_products');
        $sql = 'maas.parent_id = main_table.id';
        $sql .= ' and main_table.status = 1';
        $fields = ['qty as assocqty'];
        $collection->getSelect()->join($joinTable.' as maas', $sql, $fields)
            ->where('maas.product_id= '.$productId);
        $collection->addFilterToMap('status', 'main_table.status');
        
        foreach ($collection as $key) {
            $qty = $key->getAssocqty();
        }
        return $qty;
    }

    /**
     * function to get Base Image store view
     *
     * @param [int] $id //assign_id
     * @return string
     */
    public function getBaseImage($id) {
        $store_id = $this->_storeManager->getStore()->getId();
        $collection = $this->_data->create()->getCollection()
                ->addFieldToFilter('assign_id', $id)
                ->addFieldToFilter('is_default', 1)
                ->addFieldToFilter('type', 1)
                ->addFieldToFilter('store_view', $store_id);
        if ($collection->getSize()) {
            $item = $collection->getLastItem();
            return $item->getValue();
        }
        else return '';
    }

    /**
     * get current store
     *
     * @return void
     */
    public function getStore() {
        return $this->_storeManager->getStore();
    }

    /**
     * manage description according to store view
     */
    public function manageDescription($data, $assignId) {
        $store_id = $this->getStore()->getId();
        $collection = $this->_data->create()->getCollection()
                    ->addFieldToFilter('assign_id', $assignId)
                    ->addFieldToFilter('is_default', 1)
                    ->addFieldToFilter('type', 2)
                    ->addFieldToFilter('store_view', $store_id);
        if ($collection->getSize()) {
            foreach ($collection as $key) {
                $key->setValue($data['description'])->setId($key->getId())->save();
            }
        } else {
            $descData = [
                'type' => 2,
                'assign_id' => $assignId,
                'value' => $data['description'],
                'is_default' => 1,
                'store_view' => $store_id,
                'status' => 1
            ];
            $model = $this->_data->create();
            $model->setData($descData)->save();
        }
    }

    /**
     * get Description according to store view
     */
    public function getDescription($assignId) {
        $store_id = $this->getStore()->getId();
        $desc = '';
        $collection = $this->_data->create()->getCollection()
                    ->addFieldToFilter('assign_id', $assignId)
                    ->addFieldToFilter('is_default', 1)
                    ->addFieldToFilter('type', 2)
                    ->addFieldToFilter('store_view', $store_id);
        if ($collection->getSize()) {
            foreach ($collection as $key) {
                $desc = $key->getValue();
            }
        } else {
            $collection = $this->_data->create()->getCollection()
                    ->addFieldToFilter('assign_id', $assignId)
                    ->addFieldToFilter('is_default', 1)
                    ->addFieldToFilter('type', 2);
            foreach ($collection as $key) {
                $desc = $key->getValue(); break;
            }
        }
        return $desc;
    }

    /**
     * get minimum price product details
     */
    public function getMinimumPriceProductDetails($productId, $type = '-')
    {
        return false;
    }

    public function moveElement(&$array, $from, $to) {
        $out = array_splice($array, $from, 1);
        array_splice($array, $to, 0, $out);
    }
    
    public function getConfigProductChildrens($productId) {
        $mainProduct = $this->getProduct($productId);
        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $stockState = $objectManager->get('\Magento\CatalogInventory\Api\StockStateInterface');
        $productTypeInstance = $mainProduct->getTypeInstance();            
        $associateProducts = $productTypeInstance->getUsedProducts($mainProduct);
        $products = [];
        foreach ($associateProducts as $child) {
            $stock = $stockState->getStockQty($child->getId(), $child->getStore()->getWebsiteId());
            $products[] = [
                'price' => money_format("%.2n",$child->getPrice()),
                'stock' => $stock,
                'id' => $child->getId(),
            ];
        }
        return $products;
    }

    public function getMinimumPriceConfigProductDetails($productId, $products = [])
    {
        $tempProduct = [];
        if($productId) {
            $products = [];
            $products = $this->getMinimumPriceProductDetails($productId, 'configurable');
        }
        if ($products && count($products)>0) {
            $id = $products[0]['parentId'];
            foreach ($products as $item) {
                if($item['parentId'] == $id) {
                    $tempProduct[] = $item;
                }
            }
            return $tempProduct;
        } else {
            return false;
        }
    }

    public function getCustomOptions($product)
    {
        return $this->_customOptions->getProductOptionCollection($product);
    }
}
