<?php

namespace FiloBlu\Flow\Model;

use Exception;
use FiloBlu\Flow\Helper\LoggerProvider;
use Monolog\Logger;

/**
 * Class Map
 * @package FiloBlu\Flow\Model
 */
class Map
{

    /**
     * @var bool
     */
    public $initialized = false;
    /**
     * @var string
     */
    public $file = 'map.json';
    /**
     * @var bool
     */
    protected $_isDirectInsert = false;
    /**
     * @var bool
     */
    protected $_expandConfigurables = false;
    /**
     * @var array
     */
    protected $mappedData = [];

    /**
     * @var Logger
     */
    protected $_logger;

    /**
     * @var ChannelFactory
     */
    protected $channelFactory;

    /**
     * Map constructor.
     * @param LoggerProvider $loggerProvider
     * @param ChannelFactory $channelFactory
     */
    public function __construct(
        LoggerProvider $loggerProvider,
        ChannelFactory $channelFactory
    ) {
        $this->_logger = $loggerProvider->getLogger();
        $this->channelFactory = $channelFactory;
    }

    /**
     * @param $channel
     */
    public function load($channel)
    {
        $model_channel = $this->channelFactory->create();
        $model_channel->load($channel, 'name');

        if ($model_channel) {
            try {
                $json_content = str_replace(["\n", "\t", "\r"], '', $model_channel->getData('data'));
                $mapped_config = json_decode($json_content, true);
                $this->mappedData = array_change_key_case($mapped_config['map'], CASE_LOWER);
                $this->reorderMappedData();
                // Load custom properties in map object
                $this->_loadGeneralBehavior();
                $this->initialized = true;
                $this->_logger->info('Config - Loaded map json file');
            } catch (Exception $e) {
                $this->_logger->info('Config - Fail to load map json file');
            }
        } else {
            $this->_logger->info('Config - File for channel data not exist for json map');
        }
    }

    /**
     * Load custom properties in map object
     */
    protected function _loadGeneralBehavior()
    {
        foreach ($this->mappedData as $i => $field) {
            foreach ($field as $k => $v) {
                switch ($k) {
                    case  'direct_insert':
                        $this->_isDirectInsert = ($v == 1);

                        break;
                    case    'expand_configurables':
                        $this->_expandConfigurables = ($v == 1);
                        break;

                    case  'from':
                    case 'to':
                        $this->mappedData[$i][$k] = strtolower($v);
                        break;

                }
            }
        }
    }

    /**
     * @param $field
     * @return mixed|null
     */
    public function get($field)
    {
        if (isset($this->mappedData[$field])) {
            return $this->mappedData[$field];
        }
        return null;
    }

    /**
     * @return array
     */
    public function getFields()
    {
        return array_keys($this->mappedData);
    }

    /**
     * @return array
     */
    public function getFullMappedData()
    {
        return $this->mappedData;
    }

    /**
     * Check if parser need to insert record directly, without any kind of processing
     *
     * @return bool
     */
    public function isDirectInsert()
    {
        return $this->_isDirectInsert;
    }

    /**
     * Check if parser need to insert record directly, without any kind of processing
     *
     * @return bool
     */
    public function expandConfigurables()
    {
        return $this->_expandConfigurables;
    }

    /**
     * @param array $mappedData
     */
    public function setFullMappedData($mappedData)
    {
        $this->mappedData = $mappedData;
    }

    /**
     * @param $data
     * @return bool
     */
    public function checkData($data)
    {
        // CheckData means that each column on the CSV
        // MUST have a mapped field on the JSON mapping
        // BUT all the fields without a "FROM" should not be counted
        // because they can be static values fields (for example)
        $mappedData = array();
        foreach ($this->mappedData as $filed_name => $mapping) {
            if (!isset($mapping['from'])){
                continue;
            }
            $mappedData[$filed_name] = $mapping;
        }

        if (count($data) === count($mappedData)) {
            return true;
        }
        return false;
    }

    /*
     * Moving to the end of the array
     * all the fields of the json mapping
     * without the "from" property
     */
    private function reorderMappedData(){
        $mappedData = $this->mappedData;
        if (count($mappedData) == 0){
            return;
        }
        foreach ($mappedData as $field => $mapping) {
            if (!isset($mapping['from'])){
                // Move to the end
                $v = $mapping;
                unset($mappedData[$field]);
                $mappedData[$field] = $v;
            }
        }
        $this->mappedData = $mappedData;
    }
}
