<?php

namespace FiloBlu\Storelocator\Model\Import;

use Exception;
use Magento\Framework\App\ResourceConnection;
use Magento\ImportExport\Model\Import;
use Magento\ImportExport\Model\Import\Entity\AbstractEntity;
use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface;
use FiloBlu\Storelocator\Model\Import\Stores\RowValidatorInterface as ValidatorInterface;
use Magento\ImportExport\Model\ResourceModel\Helper;
use Magento\ImportExport\Model\ResourceModel\Import\Data;
use Magento\Framework\Validator\EmailAddress as EmailValidator;

/**
 *
 */
class Stores extends AbstractEntity
{

    const ID = 'store_id';
    const ENABLED = 'enabled';
    const IS_ENABLED_FOR_PICKUP_IN_STORE = 'is_enabled_for_pickup_in_store';
    const IS_ENABLED_SHOP_DETAILS = 'is_enabled_shop_details';
    const TITLE = 'title';
    const LATITUDE = 'latitude';
    const LONGITUDE = 'longitude';
    const STORE_IDS = 'store_ids';
    const STREET = 'street';
    const POSTCODE = 'postcode';
    const CITY = 'city';
    const REGION = 'region';
    const REGION_CODE = 'region_code';
    const COUNTRY = 'country';
    const PHONE_1 = 'phone_1';
    const PHONE_2 = 'phone_2';
    const FAX = 'fax';
    const EMAIL = 'email';
    const WEBSITE_URL = 'website_url';
    const ADDITIONAL_TEXT = 'additional_text';
    const ADDITIONAL_TEXT_2 = 'additional_text_2';
    const STORE_IFRAME_EXTERNAL = 'store_external_iframe_appointment';
    const STORE_CODE = 'store_code';
    const IS_ENABLED_FOR_RETURN_IN_STORE = 'is_enabled_for_return_in_store';
    // Working times
    const WT_MONDAY = 'wt_monday';
    const WT_TUESDAY = 'wt_tuesday';
    const WT_WEDNESDAY = 'wt_wednesday';
    const WT_THURSDAY = 'wt_thursday';
    const WT_FRIDAY = 'wt_friday';
    const WT_SATURDAY = 'wt_saturday';
    const WT_SUNDAY = 'wt_sunday';
    // Tags
    const TAGS = 'tags';
    // Google My Business
    const GMB_CAT = 'gmb_cat';
    const GMB_LANGUAGE_CODE = 'gmb_language_code';

    protected $_helper;
    protected $logInHistory = true;
    protected $needColumnCheck = false;
    protected $_permanentAttributes = [
        self::ENABLED,
        self::TITLE,
        self::STORE_IDS,
    ];
    protected $validColumnNames = [
        self::ENABLED,
        self::IS_ENABLED_FOR_PICKUP_IN_STORE,
        self::IS_ENABLED_SHOP_DETAILS,
        self::IS_ENABLED_FOR_RETURN_IN_STORE,
        self::TITLE,
        self::LATITUDE,
        self::LONGITUDE,
        self::STORE_IDS,
        self::STREET,
        self::POSTCODE,
        self::CITY,
        self::REGION,
        self::REGION_CODE,
        self::COUNTRY,
        self::PHONE_1,
        self::PHONE_2,
        self::FAX,
        self::EMAIL,
        self::WEBSITE_URL,
        self::ADDITIONAL_TEXT,
        self::ADDITIONAL_TEXT_2,
        self::STORE_IFRAME_EXTERNAL,
        self::STORE_CODE,
        self::TAGS,
        self::WT_MONDAY,
        self::WT_TUESDAY,
        self::WT_WEDNESDAY,
        self::WT_THURSDAY,
        self::WT_FRIDAY,
        self::WT_SATURDAY,
        self::WT_SUNDAY,
        self::GMB_CAT,
        self::GMB_LANGUAGE_CODE,
    ];
    /**
     * @var ResourceConnection
     */
    private $_resource;
    /**
     * @var EmailValidator
     */
    private $emailValidator;

    /**
     * @param \Magento\Framework\Json\Helper\Data $jsonHelper
     * @param \Magento\ImportExport\Helper\Data $importExportData
     * @param Data $importData
     * @param ResourceConnection $resource
     * @param Helper $resourceHelper
     * @param ProcessingErrorAggregatorInterface $errorAggregator
     * @param \FiloBlu\Storelocator\Helper\Import $helper
     * @param \Magento\Framework\Validator\EmailAddress $emailValidator
     */
    public function __construct(
        \Magento\Framework\Json\Helper\Data $jsonHelper,
        \Magento\ImportExport\Helper\Data $importExportData,
        Data $importData,
        ResourceConnection $resource,
        Helper $resourceHelper,
        ProcessingErrorAggregatorInterface $errorAggregator,
        \FiloBlu\Storelocator\Helper\Import $helper,
        EmailValidator $emailValidator
    ) {
        $this->jsonHelper = $jsonHelper;
        $this->_importExportData = $importExportData;
        $this->_resourceHelper = $resourceHelper;
        $this->_dataSourceModel = $importData;
        $this->_resource = $resource;
        $this->_connection = $resource->getConnection();
        $this->errorAggregator = $errorAggregator;
        $this->_helper = $helper;
        $this->emailValidator = $emailValidator;
    }

    public function getValidColumnNames()
    {
        return $this->validColumnNames;
    }

    /**
     * Entity type code getter.
     *
     * @return string
     */
    public function getEntityTypeCode()
    {
        return 'filoblustorelocator_import';
    }

    /**
     * Validate data row.
     *
     * @param array $rowData
     * @param int $rowNum
     * @return bool
     * @throws \Zend_Validate_Exception
     */
    public function validateRow(array $rowData, $rowNum)
    {
        if (Import::BEHAVIOR_APPEND == $this->getBehavior()) {
            // Check enabled
            if ((!isset($rowData[self::ENABLED]) || empty($rowData[self::ENABLED])) && $rowData[self::ENABLED] != 0) {
                $this->addRowError(ValidatorInterface::ERROR_ENABLED_IS_EMPTY, $rowNum);
            } else {
                if (!$this->_helper->validateEnabled($rowData[self::ENABLED])) {
                    $this->addRowError(
                        ValidatorInterface::ERROR_INVALID_ENABLED . ' - currentEnabled: ' . $rowData[self::ENABLED],
                        $rowNum
                    );
                }
            }

            // Check title
            if (!isset($rowData[self::TITLE]) || empty($rowData[self::TITLE])) {
                $this->addRowError(ValidatorInterface::ERROR_TITLE_IS_EMPTY, $rowNum);
            }
            else {
                if(!$this->_helper->validateFieldLength(self::TITLE, $rowData[self::TITLE])) {
                    $this->addRowError(ValidatorInterface::ERROR_TITLE_LENGTH . ' ' . $rowData[self::TITLE], $rowNum);
                }
            }

            // Check street
            if (isset($rowData[self::STREET]) && !empty($rowData[self::STREET])) {
                if(!$this->_helper->validateFieldLength(self::STREET, $rowData[self::STREET])) {
                    $this->addRowError(ValidatorInterface::ERROR_STREET_LENGTH . ' ' . $rowData[self::STREET], $rowNum);
                }
            }

            // Check region code
            if (isset($rowData[self::REGION_CODE]) && !empty($rowData[self::REGION_CODE])) {
                if(!$this->_helper->validateFieldLength(self::REGION_CODE, $rowData[self::REGION_CODE])) {
                    $this->addRowError(ValidatorInterface::ERROR_REGION_LENGTH . ' ' . $rowData[self::REGION_CODE], $rowNum);
                }
            }

            // Check store ids
            if ((isset($rowData[self::STORE_IDS]) && !empty($rowData[self::STORE_IDS])) && $rowData[self::STORE_IDS] != 0) {
                if (!$this->_helper->validateStoreIds($rowData[self::STORE_IDS])) {
                    $this->addRowError(
                        ValidatorInterface::ERROR_INVALID_STOREID . ' - currentStoreIds: ' . $rowData[self::STORE_IDS],
                        $rowNum
                    );
                }
            }

            // Check email
            if (isset($rowData[self::EMAIL]) && !empty($rowData[self::EMAIL])) {
                if (!$this->emailValidator->isValid(trim($rowData[self::EMAIL]))) {
                    $this->addRowError(
                        ValidatorInterface::ERROR_INVALID_EMAIL . ' ' . trim($rowData[self::EMAIL]),
                        $rowNum
                    );
                }
            }

            // Check postcode
            if (!isset($rowData[self::POSTCODE]) || empty($rowData[self::POSTCODE])) {
                $this->addRowError(ValidatorInterface::ERROR_POSTCODE_IS_EMPTY, $rowNum);
            }

            // Working Times
            if (isset($rowData[self::WT_MONDAY]) && !empty($rowData[self::WT_MONDAY])) {
                if (!$this->_helper->validateHours($rowData[self::WT_MONDAY])) {
                    $this->addRowError(ValidatorInterface::ERROR_INVALID_HOURS . ' - ' . self::WT_MONDAY, $rowNum);
                }
            }

            if (isset($rowData[self::WT_TUESDAY]) && !empty($rowData[self::WT_TUESDAY])) {
                if (!$this->_helper->validateHours($rowData[self::WT_TUESDAY])) {
                    $this->addRowError(ValidatorInterface::ERROR_INVALID_HOURS . ' - ' . self::WT_TUESDAY, $rowNum);
                }
            }
            if (isset($rowData[self::WT_WEDNESDAY]) && !empty($rowData[self::WT_WEDNESDAY])) {
                if (!$this->_helper->validateHours($rowData[self::WT_WEDNESDAY])) {
                    $this->addRowError(ValidatorInterface::ERROR_INVALID_HOURS . ' - ' . self::WT_WEDNESDAY, $rowNum);
                }
            }
            if (isset($rowData[self::WT_THURSDAY]) && !empty($rowData[self::WT_THURSDAY])) {
                if (!$this->_helper->validateHours($rowData[self::WT_THURSDAY])) {
                    $this->addRowError(ValidatorInterface::ERROR_INVALID_HOURS . ' - ' . self::WT_THURSDAY, $rowNum);
                }
            }
            if (isset($rowData[self::WT_FRIDAY]) && !empty($rowData[self::WT_FRIDAY])) {
                if (!$this->_helper->validateHours($rowData[self::WT_FRIDAY])) {
                    $this->addRowError(ValidatorInterface::ERROR_INVALID_HOURS . ' - ' . self::WT_FRIDAY, $rowNum);
                }
            }
            if (isset($rowData[self::WT_SATURDAY]) && !empty($rowData[self::WT_SATURDAY])) {
                if (!$this->_helper->validateHours($rowData[self::WT_SATURDAY])) {
                    $this->addRowError(ValidatorInterface::ERROR_INVALID_HOURS . ' - ' . self::WT_SATURDAY, $rowNum);
                }
            }
            if (isset($rowData[self::WT_SUNDAY]) && !empty($rowData[self::WT_SUNDAY])) {
                if (!$this->_helper->validateHours($rowData[self::WT_SUNDAY])) {
                    $this->addRowError(ValidatorInterface::ERROR_INVALID_HOURS . ' - ' . self::WT_SUNDAY, $rowNum);
                }
            }
        }

        return !$this->getErrorAggregator()->isRowInvalid($rowNum);
    }

    /**
     * Create Advanced price data from raw data.
     *
     * @return bool Result of operation.
     * @throws Exception
     */
    protected function _importData()
    {
        if (Import::BEHAVIOR_APPEND == $this->getBehavior()) {
            $this->updateData();
        }

        return true;
    }

    /**
     * @return $this
     * @throws \Exception
     */
    protected function updateData()
    {
        $i = 0;

        while ($bunch = $this->_dataSourceModel->getNextBunch()) {
            $entityList = [];
            foreach ($bunch as $rowNum => $rowData) {
                if ($this->getErrorAggregator()->hasToBeTerminated()) {
                    $this->getErrorAggregator()->addRowToSkip($rowNum);
                    continue;
                }

                $i++;

                foreach ($rowData as $key => $value) {
                    $entityList[$i][$key] = $value;
                }
            }

            $this->countItemsCreated += $i;

            $this->_helper->importDbData($entityList);
        }

        return $this;
    }

}
