<?php

namespace Webkul\WebkulCsvImportBundle\Connector\Reader\Csv;

use Akeneo\Tool\Component\Connector\ArrayConverter\ArrayConverterInterface;
use Akeneo\Tool\Component\Connector\Reader\File\Csv\Reader;
use Akeneo\Tool\Component\Connector\Reader\File\FileIteratorFactory;
use Akeneo\Tool\Component\Connector\Reader\File\FileReaderInterface;
use Akeneo\Tool\Component\Connector\Reader\File\MediaPathTransformer;
use Webkul\WebkulCsvImportBundle\Services\WebkulCsvConnector;

class ProductModelReader extends Reader implements FileReaderInterface
{
    /** @var MediaPathTransformer */
    protected $mediaPathTransformer;

    public $connectorService;

    protected $templateStore = null;
    /**
     * @param FileIteratorFactory     $fileIteratorFactory
     * @param ArrayConverterInterface $converter
     * @param MediaPathTransformer    $mediaPathTransformer
     * @param WebkulCsvConnector      $connectorService
     * @param array                   $options
     */
    public function __construct(
        FileIteratorFactory $fileIteratorFactory,
        ArrayConverterInterface $converter,
        MediaPathTransformer $mediaPathTransformer,
        WebkulCsvConnector $connectorService,
        array $options = []
    ) {
        parent::__construct($fileIteratorFactory, $converter, $options);

        $this->mediaPathTransformer = $mediaPathTransformer;
        $this->connectorService     = $connectorService;
    }

    /**
     * {@inheritdoc}
     */
    public function read()
    {        
        $transformedData = [];
        $productData = [];
        
        $this->connectorService->setStepExecution($this->stepExecution);
        $jobParameters = $this->stepExecution->getJobParameters();
        $allJobParameters       = $this->stepExecution->getJobParameters()->all();
        if(!$this->templateStore) {
            $template            = $this->connectorService->getTemplateStore($allJobParameters['exportProfile']);
            $storeTemplateData   = json_decode($template->getRawValues(), true);
            $this->templateStore = isset($storeTemplateData['csvImportMapping']) ? $storeTemplateData['csvImportMapping'] : [];
        }
        $filePath = $jobParameters->get('filePath');
        if (null === $this->fileIterator) {
            $delimiter = $jobParameters->get('delimiter');
            $enclosure = $jobParameters->get('enclosure');
            $defaultOptions = [
                'reader_options' => [
                    'fieldDelimiter' => $delimiter,
                    'fieldEnclosure' => $enclosure,
                ],
            ];
            $this->fileIterator = $this->fileIteratorFactory->create(
                $filePath,
                array_merge($defaultOptions, $this->options)
            );
            $this->fileIterator->rewind();
        }

        $this->fileIterator->next();
        
        if ($this->fileIterator->valid() && null !== $this->stepExecution) {
            $this->stepExecution->incrementSummaryInfo('item_position');
        }
        
        $productTypeField = isset($this->templateStore['extraMapping']['productTypeFieldName']) ? $this->templateStore['extraMapping']['productTypeFieldName'] : '';
        $productModelType =  isset($this->templateStore['extraMapping']['modelProductType']) ? $this->templateStore['extraMapping']['modelProductType'] : '';

        if(!empty($productTypeField) && !empty($productModelType) && $productModelType != '') {
            $correctData = false;
            
            do {            
                $data = $this->fileIterator->current();
                
                if (null === $data) {
                    return null;
                }

                $headers = $this->fileIterator->getHeaders();
                
                $countHeaders = count($headers);
                $countData = count($data);
                
                $this->checkColumnNumber($countHeaders, $countData, $data, $filePath);
                
                if ($countHeaders > $countData) {
                    $missingValuesCount = $countHeaders - $countData;
                    $missingValues = array_fill(0, $missingValuesCount, '');
                    $data = array_merge($data, $missingValues);
                }
                
                $data = array_combine($this->fileIterator->getHeaders(), $data);

                if(isset($data[$productTypeField]) && $data[$productTypeField] == $productModelType) {
                    $correctData = true;
                    $this->fileIterator->next();
                } else {
                    $correctData = false;
                }                
            } while ($correctData == true);
        } else {
            $this->stepExecution->addWarning('Template have missing values of productType field or modelProductType', [], new \DataInvalidItem([]));
            return;
        }

        $transformedData = $this->transformData($data);
        $identifier = $this->connectorService->getIdentifierAttr();

        if(isset($transformedData[$identifier])) {
            $productData['code'] = $transformedData[$identifier];
        }
        $currency = $jobParameters->all()['filters']['structure']['currency'];
        $scope = $jobParameters->all()['filters']['structure']['scope'];
        $locale = isset($jobParameters->all()['filters']['structure']['locales'][0]) ? $jobParameters->all()['filters']['structure']['locales'][0] : ''; 
        $values = $this->connectorService->convertTransformedData($transformedData, $scope, $locale, $currency, $this->templateStore['extraMapping']['multiValueSeperator']);

        if(isset($this->templateStore['extraMapping']['familyVariantFieldName']) && isset($data[$this->templateStore['extraMapping']['familyVariantFieldName']])) {
            $productData['family_variant'] = isset($data[$this->templateStore['extraMapping']['familyVariantFieldName']]) ? $data[$this->templateStore['extraMapping']['familyVariantFieldName']] : null;
        }
        //  else {
        //     $this->stepExecution->addWarning('Family varient field must not be blanked.', [], new \DataInvalidItem([]));
        //     return;
        // }

        // if(!isset($this->templateStore['extraMapping']['categoryFieldName']) && !isset($data[$this->templateStore['extraMapping']['categoryFieldName']])) {
        //     $this->stepExecution->addWarning('Category field must not be blanked.', [], new \DataInvalidItem([]));
        //     return;
        // }

        // if(!isset($this->templateStore['extraMapping']['exportCategoryLabel']) && !isset($data[$this->templateStore['extraMapping']['exportCategoryLabel']])) {
        //     $this->stepExecution->addWarning('Export category field must not be blanked.', [], new \DataInvalidItem([]));
        //     return;
        // }

        if(isset($this->templateStore['extraMapping']['categoryFieldName']) 
            && !empty($this->templateStore['extraMapping']['categoryFieldName'])
            && $this->templateStore['extraMapping']['exportCategoryLabel'] == 'true'
        ) {
            $categories = explode('/',$data[$this->templateStore['extraMapping']['categoryFieldName']]);
            if(!empty($categories)) {
                $category = [];
                foreach ($categories as $value) {
                    if($value) {

                        $category[] = $value;
                    }
                }
                $productData['categories'] = $category;
            }

        }
        // $productData['groups'] = [];

        if(isset($this->templateStore['extraMapping']['parentCode']) && !empty($this->templateStore['extraMapping']['parentCode']) && isset($data[$this->templateStore['extraMapping']['parentCode']]) && !empty($data[$this->templateStore['extraMapping']['parentCode']])) {
            $productData['parent'] = $data[$this->templateStore['extraMapping']['parentCode']];
        } else {
            $productData['parent'] = null;
        }
        
        $productData['values'] = $values;
        if (!is_array($productData) || !isset($productData['values'])) {
            return $productData;
        }

        // $productData['values'] = $this->mediaPathTransformer->transform($productData['values'], $this->fileIterator->getDirectoryPath());
        
        return $productData;
    }

    public function transformData($data)
    {   
        $response = [];
        $keys = array_keys($data);
        foreach ($keys as $key) {
            $result = [];
            if(isset($this->templateStore['rawValues'][$key])) {
                if($this->templateStore['rawValues'][$key]['type'] == 'multiple') {

                    $result = $this->multipleFieldResolve($data, $this->templateStore, $key);
                } else if($this->templateStore['rawValues'][$key]['type'] == 'concatenate') {
                    
                    $result = $this->multipleFieldResolve($data, $this->templateStore, $key, 'concate');
                } else {
                    $result = $this->simpleFieldResolve($data, $this->templateStore, $key);                        
                }
                if($result) {
                    foreach ($result as $attrKey => $attrValue) {                            
                        if($attrValue) {
                            $response[$attrKey] = $attrValue;
                        }
                    }
                }                       
            }
        }

        return $response;
    }

    public function simpleFieldResolve($data, $mapping, $key)
    {        
        $attrs = $mapping['rawValues'][$key]['attributes'];
        $response = [];
        if(isset($mapping['rawValues'][$key]['attributefieldformat'][0]) && isset($mapping['rawValues'][$key]['attributefieldformat'][1]) && isset($mapping['rawValues'][$key]['attributefieldformat'][2]) && $mapping['rawValues'][$key]['attributefieldformat'][0] == 'attributename' && $mapping['rawValues'][$key]['attributefieldformat'][1] == 'seperator' && $mapping['rawValues'][$key]['attributefieldformat'][2] == 'attributevalue') {
            $values = explode($mapping['extraMapping']['productFormatSeperator'],$data[$key]);
            if(count($values)  > 1) {
                unset($values[0]);
            } else {
                $response[$attrs] = $values[0];
            }
            if(isset($values[1])) {
                $response[$attrs] = $values[1];
            }

        } else if($mapping['rawValues'][$key]['attributefieldformat'][0] == 'attributename') {
            $response[$attrs] = $data[$key];
        } else if($mapping['rawValues'][$key]['attributefieldformat'][0] == 'attributevalue') {
            $response[$attrs] = $data[$key];
        } else {
            $this->stepExecution->addWarning('Single CSV field must have format of attributename + saperator + attributevalue Or only attributevalue', [], new \DataInvalidItem([]));
        }
        
        return $response;
    }

    public function multipleFieldResolve($data, $mapping, $key, $type = 'mutiple' )
    {
        $saperator = $mapping['extraMapping']['multiValueSeperator'];
        if($type == 'concate') {
            $saperator = '_';
        }

        if(isset($mapping['rawValues'][$key]['attributefieldformat'][0]) && isset($mapping['rawValues'][$key]['attributefieldformat'][1]) && isset($mapping['rawValues'][$key]['attributefieldformat'][2]) && $mapping['rawValues'][$key]['attributefieldformat'][0] == 'attributename' && $mapping['rawValues'][$key]['attributefieldformat'][1] == 'seperator' && $mapping['rawValues'][$key]['attributefieldformat'][2] == 'attributevalue' && $mapping['extraMapping']['productFormatSeperator'] != $mapping['extraMapping']['multiValueSeperator']) {
            $response = [];
            $attrs = $mapping['rawValues'][$key]['attributes'];

            if(isset($attrs)) {
                if(is_array($attrs)) {
                    if($type != 'concate'){
                        $values = explode($mapping['extraMapping']['productFormatSeperator'],$data[$key]);                    

                        foreach($attrs as $key => $attr){
                            foreach ($values as $keys => $value) {
                                $attData = explode('=',$value); 
                                if(strpos(strtolower($value), $attr) !== false){
                                    $response[$attr] = $attData[1];
                                }
                            }
                        }
                    } else{
                        $values = explode($saperator,$data[$key]);                    

                        foreach($attrs as $key => $attr){
                            foreach ($values as $keys => $value) {
                                $attData = explode($mapping['extraMapping']['productFormatSeperator'],$value); 
                                if(strpos(strtolower($value), $attr) !== false){
                                    $response[$attr] = $attData[1];
                                }
                            }
                        }
                    }
                } else {
                    $response[$attrs] = $data[$key];
                }
            } 

            if($response) {
                return $response;
            }

        } 
        // else {

        //     $this->stepExecution->addWarning('Multiple CSV field must have format of attributename + saperator + attributevalue Or the Product Format saperator can not be same as multiple value saperator', [], new \DataInvalidItem([]));
        // }
        
    }

    /**
     * @return array
     */
    protected function getArrayConverterOptions()
    {
        $jobParameters = $this->stepExecution->getJobParameters();

        return [
            // for the array converters
            'mapping'           => [
                $jobParameters->get('familyColumn')     => 'family',
                $jobParameters->get('categoriesColumn') => 'categories',
                $jobParameters->get('groupsColumn')     => 'groups'
            ],
            'with_associations' => false,

            // for the delocalization
            'decimal_separator' => $jobParameters->get('decimalSeparator'),
            'date_format'       => $jobParameters->get('dateFormat')
        ];
    }
}