<?php

namespace Benhauer\Salesmanago\Model;

use \Magento\Framework\Model\AbstractModel as MagentoAbstractModel;
use \Magento\Framework\Model\Context;
use \Magento\Framework\Registry;
use \Magento\Framework\UrlInterface;
use \Magento\Framework\App\Config\Storage\WriterInterface;

use \Magento\Store\Model\StoreManagerInterface;
use \Magento\Config\Model\ResourceModel\Config\Data\CollectionFactory as ConfigCollection;
use \Magento\Framework\App\Config\ScopeConfigInterface;
use \Magento\Framework\App\Cache\Manager as CacheManager;

use \SALESmanago\Entity\Settings;
use \SALESmanago\Factories\FactoryOrganizer;

abstract class AbstractModel extends MagentoAbstractModel
{
    const
        SETTINGS_PATH = 'benhauer_salesmanago/general',
        SETTINGS_PATH_SM_STORE_ID = 'benhauer_salesmanago/storeId',

        P_CONFIG = 'config',
        P_OPTIONS = 'options',
        P_PROPERTIES = 'properties',
        ACTIVE = 'active',
        CLIENT_ID = 'clientId',
        SHA = 'sha',
        API_KEY = 'apiKey',
        API_SECRET = 'apiSecret',
        ENDPOINT = 'endpoint',
        TOKEN = 'token',
        EMAIL = 'email',
        WEB_PUSH = 'webPush',
        SYNC_RULE = 'synchronizeRule',

        LANG = 'lang',
        C_MAIN = 'colorMain',
        C_MAIN_FONT = 'colorMainFont',
        C_ADDITIONAL = 'colorAdditional',
        C_ADDITIONAL_FONT = 'colorAdditionalFont',

        O_TYPES = 'orderTypes',
        STORE_ID = 'storeId',

        OWNER = 'owner',
        E_COOKIE_TIME = 'eventCookie',
        C_EVENT_COOKIE_TIME = 'eventCookie',

        C_CALLBACK_OPTIN = 'callbackOptIn',
        C_CALLBACK_OPTOUT = 'callbackOptOut',

        C_CLIENT_ID = 'clientId',
        C_SHA = 'sha',
        C_ENDPOINT = 'endpoint',

        C_OWNER_EMAIL = 'ownerEmail',
        C_SYNCHRONIZE = 'synchronize',
        C_DOUBLE_OPT_IN = 'doubleOptIn',
        C_LOCATION = 'location',

        C_API_KEY = 'apiKey',
        C_TOKEN = 'token',
        C_EXPIRES_TOKEN_AT = 'expiresTokenAt',
        C_UPDATED_AT = 'updatedAt',
        C_CREATE_AT = 'createdAt',

        C_LANG = 'lang',
        C_COLOR = 'color',
        C_COLOR_MAIN = 'main',
        C_COLOR_ADDITIONAL = 'additional',
        C_COLOR_ADDITIONAL_FONT = 'additional_font',

        C_PATH_DEVIDER = '/',
        C_SETTINGS_PATH = 'salesmanago/settings',
        C_STORES_WITH_CONFIGURATION = 'storesWithConfiguration',
        C_CHECK_STORE_SCOPE_ID = 'checkStoreScopeId',

        C_PLATFORM_SETTING_PATH = 'salesmanago_platform_settings/',
        C_ACCOUNT_SETTINGS_PATH = 'salesmanago_account_settings/',

        C_PATH_TYPE_GENERAL = 'general/',
        C_PATH_TYPE_COLORS = 'color/',
        C_PATH_TYPE_EVENTS = 'events/',
        C_PATH_TYPE_CALLBACKS = 'callbacks/',
        C_PATH_TYPE_API_DOUBLE_OPT_IN = 'apiDoubleOptIn/',

        TAGS = 'tags',
        T_NEWS = 'subscription',
        T_REGISTER = 'registration',
        T_LOGIN = 'login',
        T_PURCHASE = 'purchase',
        T_GUEST_PURCHASE ='purchaseGuest',

        DOUBLE_OPT_IN = 'useApiDoubleOptIn',
        DOUBLE_OPT_IN_EMAIL_TEMPLATE_ID = 'apiDoubleOptInEmailTemplateId',
        DOUBLE_OPT_IN_EMAIL_ACCOUNT_ID = 'apiDoubleOptInEmailAccountId',
        DOUBLE_OPT_IN_EMAIL_SUBJECT_ID = 'apiDoubleOptInEmailSubject';

    public $cacheManager;
    public $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT;
    public $scopeId = 0;

    public $updateAtTime = 0;
    public $scopeConfigInterface;

    public $storeManager;
    public $configWriter;
    public $collectionFactory;

    public $defaultValue = [];
    public $userValue = [];

    public $factoryOrganizer;

    public $settingItem = [];

    public function __construct(
        Context $context,
        Registry $registry,
        StoreManagerInterface $storeManager,
        WriterInterface $configWriter,
        ConfigCollection $collectionFactory,
        FactoryOrganizer $factoryOrganizer,
        ScopeConfigInterface $scopeConfigInterface,
        CacheManager $cacheManager
    ) {
        parent::__construct($context, $registry);
        $this->cacheManager = $cacheManager;
        $this->scopeConfigInterface = $scopeConfigInterface;

        $this->storeManager = $storeManager;
        $this->configWriter = $configWriter;
        $this->collectionFactory = $collectionFactory;
        $this->factoryOrganizer = $factoryOrganizer;

        $this->defaultValue = [
            'domain' => $this->storeManager
                ->getStore($this->scopeId)
                ->getBaseUrl(UrlInterface::URL_TYPE_WEB),
            self::TAGS => [
                self::T_LOGIN => 'magento2_login',
                self::T_NEWS => 'magento2_newsletter',
                self::T_PURCHASE => 'magento2_purchase',
                self::T_REGISTER => 'magento2_register',
                self::T_GUEST_PURCHASE => 'magento2_guest_purchase'
            ],
            self::E_COOKIE_TIME => '3',
            self::ACTIVE => false,
            self::C_CREATE_AT => time(),
            self::C_UPDATED_AT => time()
        ];
    }

    /**
     * @param string $path - settings path;
     * @param mixed $value - settings value;
     */
    protected function setConfigItem($path, $value)
    {
        $this->scope = ($this->scopeId != 0) ? 'stores' : $this->scope;

        $this->configWriter->save(
            $path,
            $value,
            $this->scope,
            $this->scopeId
        );
    }

    /**
     * @param string $path - settings path;
     * @return string $item - config item value;
     */
    protected function getConfigItem($path)
    {
        $scopeCode = $this->storeManager->getStore($this->scopeId)->getCode();
        $scope = $this->scope;

        if ($scopeCode == ScopeConfigInterface::SCOPE_TYPE_DEFAULT) {
            $scopeCode = 0;
        }

        $settingItem = $this->collectionFactory
            ->create()
            ->addFieldToFilter('scope_id', array('eq' => $this->scopeId))
            ->addFieldToFilter('path', array('eq' => $path))
            ->getFirstItem()
            ->getData();


        $item = isset($settingItem['value']) ? $settingItem['value'] : null;
        return $item;
    }

    private function getSettingItem($scopeId, $path) {
        return $this->collectionFactory
            ->create()
            ->addFieldToFilter('scope_id', array('eq' => $scopeId))
            ->addFieldToFilter('path', array('eq' => $path))
            ->getFirstItem()
            ->getData();
    }


    /**
     * Check for existing configuration for current store id
     * @return boolean - true - config exist, false - no
     */
    public function isPluginConfActive()
    {
        $checkScopeId = $this->checkScopeId();
        $clientId = $this->getClientId();

        return ($clientId && $checkScopeId);
    }

    /**
     * Set scope id - this need for check which stores configuration set (for which store view),
     * magento load next configuration if curret (by store id) is not exist;
     *
     * @return $this;
     */
    public function setScopeCheckId($scopeId)
    {
        $path = self::C_SETTINGS_PATH . self::C_PATH_DEVIDER . self::C_CHECK_STORE_SCOPE_ID;
        $this->setConfigItem($path, $scopeId);
        return $this;
    }

    /**
     * Check if curret scope (by scope id) is seted in configuration,
     * in this way script could check if some configuration exist for specific store id;
     */
    public function checkScopeId()
    {
        $path = self::C_SETTINGS_PATH . self::C_PATH_DEVIDER . self::C_CHECK_STORE_SCOPE_ID;
        $checkScopeId = $this->getConfigItem($path);

        return ($this->scopeId == $checkScopeId);
    }

    /**
     * Clear all cache values;
     */
    protected function clearCache()
    {
        /*$this->cacheManager->flush($this->cacheManager->getAvailableTypes());*/
        $this->cacheManager->clean($this->cacheManager->getAvailableTypes());
    }

    /**
     * @param string $id - sm client id;
     * @return $this;
     */
    public function setClientId($id)
    {
        $this->setConfigItem(
            self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_GENERAL . self::C_CLIENT_ID,
            $id
        );

        return $this;
    }

    /**
     * @return string sm clientId;
     */
    public function getClientId()
    {
        return $this->getConfigItem(self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_GENERAL . self::C_CLIENT_ID);
    }

    /**
     * @return string sm clientId;
     */
    public function getClientsIds()
    {

        $stores = $this->storeManager->getStores();
        $scopeId = $this->scopeId;
        $clientIds = [];

        foreach ($stores as $store) {
            $storeId = $store->getId();
            $this->scopeId = $storeId;
            $clientId = $this->getConfigItem(self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_GENERAL . self::C_CLIENT_ID);

            if ($clientId) {
                array_push($clientIds, $clientId);
            }
        }

        $this->scopeId = $scopeId;
        return $clientIds;
    }

    /**
     * @param string $sha - sm sha;
     * @return $this;
     */
    public function setSHA($sha)
    {
        $this->setConfigItem(
            self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_GENERAL . self::C_SHA,
            $sha
        );

        return $this;
    }

    /**
     * @return string sm SHA;
     */
    public function getSHA()
    {
        return $this->getConfigItem(self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_GENERAL . self::C_SHA);
    }

    /**
     * @param string $apiKey - sm api key;
     * @return $this;
     */
    public function setApiKey($apiKey)
    {
        $this->setConfigItem(
            self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_GENERAL . self::C_API_KEY,
            $apiKey
        );

        return $this;
    }

    /**
     * @return string sm Api Key;
     */
    public function getApiKey()
    {
        return $this->getConfigItem(self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_GENERAL . self::C_API_KEY);
    }

    /**
     * @param string $ownerEmail - sm owner email;
     * @return $this;
     */
    public function setOwner($ownerEmail)
    {
        $this->setConfigItem(
            self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_GENERAL . self::C_OWNER_EMAIL,
            $ownerEmail
        );

        return $this;
    }

    /**
     * @return string sm owner email;
     */
    public function getOwnerEmail()
    {
        return $this->getConfigItem(self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_GENERAL . self::C_OWNER_EMAIL);
    }

    /**
     * @param string $endpoint - sm app endpoint;
     * @return $this;
     */
    public function setEndpoint($endpoint)
    {
        $this->setConfigItem(
            self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_GENERAL . self::C_ENDPOINT,
            $endpoint
        );

        return $this;
    }

    /**
     * @return string sm endpoint;
     */
    public function getEndpoint()
    {
        return $this->getConfigItem(self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_GENERAL . self::C_ENDPOINT);
    }

    /**
     * @param string $token - sm token;
     * @return $this;
     */
    public function setToken($token)
    {
        $this->setConfigItem(
            self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_GENERAL . self::C_TOKEN,
            $token
        );

        return $this;
    }

    /**
     * @return string sm token;
     */
    public function getToken()
    {
        return $this->getConfigItem(self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_GENERAL . self::C_TOKEN);
    }

    /**
     * Set expires token time
     */
    public function setExpiresTokenAt()
    {
        $timestamp = time();
        $now = date("Y-m-d H:i:s", $timestamp);

        $this->setConfigItem(
            self::C_SETTINGS_PATH . self::C_PATH_DEVIDER . self::C_EXPIRES_TOKEN_AT,
            strtotime("$now +29 Days + 20 Hours")
        );

        return $this;
    }

    /**
     * Get expires token time
     */
    public function getExpiresTokenAt()
    {
        return $this->getConfigItem(self::C_SETTINGS_PATH . self::C_EXPIRES_TOKEN_AT);
    }

    /**
     * Set update at time
     */
    public function setUpdatedAtTime()
    {

        $this->setConfigItem(
            self::C_SETTINGS_PATH . self::C_PATH_DEVIDER . self::C_UPDATED_AT,
            time()
        );

        return $this;
    }

    /**
     * Get update at time
     */
    public function getUpdatedAtTime()
    {
        return $this->getConfigItem(self::C_SETTINGS_PATH . self::C_PATH_DEVIDER . self::C_UPDATED_AT);
    }

    /**
     * Set created at time
     */
    public function setCreatedAtTime()
    {

        $this->setConfigItem(
            self::C_SETTINGS_PATH . self::C_PATH_DEVIDER . self::C_CREATE_AT,
            time()
        );

        return $this;
    }

    /**
     * Get created at time
     */
    public function getCreatedAtTime()
    {
        return $this->getConfigItem(self::C_SETTINGS_PATH . self::C_PATH_DEVIDER . self::C_CREATE_AT);
    }

    /**
     * @param string - sm lang;
     * @return $this
     */
    public function setLang($lang)
    {
        $this->setConfigItem(
            self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_GENERAL . self::C_LANG,
            $lang
        );

        return $this;
    }

    /**
     * @return string sm lang;
     */
    public function getLang()
    {
        return $this->getConfigItem(self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_GENERAL . self::C_LANG);
    }

    /**
     * @param array $arrayColors an associative array (main, mainFont, additional, additionalFont) with colors
     * @return $this
     */
    public function setColors($arrayOfColors)
    {
        if (empty($arrayOfColors)) {
            return $this;
        }

        foreach ($arrayOfColors as $colorName => $color) {
            $this->setConfigItem(
                self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_COLORS . $colorName,
                $color
            );
        }

        return $this;
    }

    /**
     * @param array $array - an associative array of tags, where key is self::CONST name of tag & value is a tag;
     */
    public function setTags($array = [])
    {
        $array = empty($array) ? $this->defaultValue[self::TAGS] : $array;

        foreach ($array as $tagName => $tag) {
            $this->setConfigItem(
                self::C_PLATFORM_SETTING_PATH . self::TAGS . self::C_PATH_DEVIDER . $tagName,
                $tag
            );
        }
        return $this;
    }

    /**
     * @param string self::CONST tag name
     * @return mixed array of tags || string tag
     */
    public function getTags($tagName = '')
    {
        if (!empty($tagName)) {
            return $this->getConfigItem(self::C_PLATFORM_SETTING_PATH . self::TAGS . self::C_PATH_DEVIDER . $tagName);
        }

        $tags = [
            self::T_NEWS => self::getTags(self::T_NEWS),
            self::T_REGISTER => self::getTags(self::T_REGISTER),
            self::T_LOGIN => self::getTags(self::T_LOGIN),
            self::T_PURCHASE => self::getTags(self::T_PURCHASE),
            self::T_GUEST_PURCHASE => self::getTags(self::T_GUEST_PURCHASE)
        ];

        return $tags;
    }

    /**
     * @param integer $hours
     */
    public function setExtEventCookieLifeTime($hours = 3)
    {
        $this->setConfigItem(
            self::C_PLATFORM_SETTING_PATH . self::C_PATH_TYPE_EVENTS . self::C_EVENT_COOKIE_TIME,
            $hours
        );
        return $this;
    }

    /**
     * @return integer - external cookie life time in hours
     */
    public function getExtEventCookieLifeTime()
    {
        return $this->getConfigItem(self::C_PLATFORM_SETTING_PATH . self::C_PATH_TYPE_EVENTS . self::C_EVENT_COOKIE_TIME);
    }

    /**
     * Get opt in configuration;
     * @return array
     */
    public function getDoubleOptInData()
    {
        $answer = [
            self::DOUBLE_OPT_IN => boolval($this->getConfigItem(self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_API_DOUBLE_OPT_IN . self::DOUBLE_OPT_IN)),
            self::DOUBLE_OPT_IN_EMAIL_TEMPLATE_ID => $this->getConfigItem(self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_API_DOUBLE_OPT_IN . self::DOUBLE_OPT_IN_EMAIL_TEMPLATE_ID),
            self::DOUBLE_OPT_IN_EMAIL_ACCOUNT_ID => $this->getConfigItem(self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_API_DOUBLE_OPT_IN . self::DOUBLE_OPT_IN_EMAIL_ACCOUNT_ID),
            self::DOUBLE_OPT_IN_EMAIL_SUBJECT_ID => $this->getConfigItem(self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_API_DOUBLE_OPT_IN . self::DOUBLE_OPT_IN_EMAIL_SUBJECT_ID)
        ];

        return $answer;
    }

    /**
     * Get synchronize rule state
     * @return boolean;
     */
    public function getSynchronize()
    {
        return boolval($this->getConfigItem(self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_GENERAL . self::C_SYNCHRONIZE));
    }

    /**
     * @return $this;
     */
    public function setCallbacks()
    {
        $storeDomain = $this->storeManager
            ->getStore($this->scopeId)
            ->getBaseUrl(UrlInterface::URL_TYPE_WEB);

        $url = [
            self::C_CALLBACK_OPTIN => $storeDomain . "salesmanago/newsletter/in?email=\$email\$&key=sha1(\$email\${$this->getClientId()})",
            self::C_CALLBACK_OPTOUT => $storeDomain . "salesmanago/newsletter/out?email=\$email\$&key=sha1(\$email\${$this->getClientId()})"
        ];

        $this->setConfigItem(
            self::C_PLATFORM_SETTING_PATH . self::C_PATH_TYPE_CALLBACKS . self::C_CALLBACK_OPTIN,
            $url[self::C_CALLBACK_OPTIN]
        );

        $this->setConfigItem(
            self::C_PLATFORM_SETTING_PATH . self::C_PATH_TYPE_CALLBACKS . self::C_CALLBACK_OPTOUT,
            $url[self::C_CALLBACK_OPTOUT]
        );

        return $this;
    }

    /**
     * Gets all data core config for SM Service
     * @return array of config
     */
    public function getDataCoreConfig()
    {
        $clientId = $this->getClientId();

        if ($clientId == null && $this->scopeId != 0) {
            $this->scopeId = 0;
            $this->getDataCoreConfig();
        }

        $answer = [
            'tags' => self::getTags(),
            'active' => false,
            'createdAt' => $this->getCreatedAtTime(),
            'updatedAt' => $this->getUpdatedAtTime(),
            'clientId' => $this->getClientId(),
            'sha' => $this->getSHA(),
            'apiKey' => $this->getApiKey(),
            'owner' => $this->getOwnerEmail(),
            'endpoint' => $this->getEndpoint(),
            'token' => $this->getToken(),
            'expiresTokenAt' => $this->getExpiresTokenAt(),

            'properties' => [
                'lang' => $this->getLang(),
                'color' => [
                    'main' => '#A8E622',
                    'mainFont' => '#D82424',
                    'additional' => '#DA4646',
                    'additionalFont' => '#B57C7C'
                ]
            ]

        ];

        $doubleOptIn = $this->getDoubleOptInData();
        $answer = !empty($doubleOptIn) ? array_merge($answer, $doubleOptIn) : $answer;

        return $answer;
    }

    public function removePluginConfiguration()
    {
        try {
            $pathToRemove = [
                self::C_CHECK_STORE_SCOPE_ID => self::C_SETTINGS_PATH . self::C_PATH_DEVIDER . self::C_CHECK_STORE_SCOPE_ID,
                self::C_CLIENT_ID => self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_GENERAL . self::C_CLIENT_ID,
                self::C_SHA => self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_GENERAL . self::C_SHA,
                self::C_API_KEY => self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_GENERAL . self::C_API_KEY,
                self::C_OWNER_EMAIL => self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_GENERAL . self::C_OWNER_EMAIL,
                self::C_ENDPOINT => self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_GENERAL . self::C_ENDPOINT,
                self::C_TOKEN => self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_GENERAL . self::C_TOKEN,
                self::C_EXPIRES_TOKEN_AT => self::C_SETTINGS_PATH . self::C_PATH_DEVIDER . self::C_EXPIRES_TOKEN_AT,
                self::C_UPDATED_AT => self::C_SETTINGS_PATH . self::C_PATH_DEVIDER . self::C_UPDATED_AT,
                self::C_CREATE_AT => self::C_SETTINGS_PATH . self::C_PATH_DEVIDER . self::C_CREATE_AT,
                self::C_LANG => self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_GENERAL . self::C_LANG,
                self::C_PATH_TYPE_COLORS => self::C_ACCOUNT_SETTINGS_PATH . self::C_PATH_TYPE_COLORS,
                self::C_PATH_TYPE_COLORS => self::C_PLATFORM_SETTING_PATH . self::TAGS,
                self::C_PATH_TYPE_CALLBACKS => self::C_PLATFORM_SETTING_PATH . self::C_PATH_TYPE_CALLBACKS
            ];

            foreach ($pathToRemove as $path) {
                $this->configWriter->delete($path, $this->scope, $this->scopeId);
            }

            $this->clearCache();
            return true;
        } catch (\Exception $e) {
            return false;
        }
    }
    /**
     * Sets default configuration afte
     */
    public function setDefaultAdditionalDataAfterInit()
    {
        $this
            ->setTags()
            ->setExtEventCookieLifeTime()
            ->setCallbacks()
            ->_setSMStoreId(
                $this->storeManager->getStore($this->scopeId)->getUrl()
            );
    }

    /**
     *  Sets the ids of stores which is configured (logged in)
     */
    public function setsStoreIdsWithInitClient($storeId)
    {
        $path = self::C_SETTINGS_PATH . self::C_PATH_DEVIDER . self::C_STORES_WITH_CONFIGURATION;
        $ids = $this->scopeConfigInterface->getValue($path);

//      if (!empty($ids)) {
//          $ids = explode($ids, ',');
//          $ids = in_array($ids, $storeId) ?
//      }

        $this->configWriter->save($path, $value);
        return $this;
    }

    public function update($id, $settings)
    {
        $this->setExpiresTokenAt();
    }

    public function prepareValue($settings, $default = false)
    {
        $this->userValue = $settings;
        if ($default) {
            $this->userValue = $this->arrayMergeRecursiveDistinct(
                $this->defaultValue,
                $settings
            );
        }

        return $this;
    }

    public function buildValue()
    {
        return json_encode($this->userValue);
    }

    public function arrayMergeRecursiveDistinct(array &$array1, array &$array2)
    {
        $merged = $array1;

        foreach ($array2 as $key => &$value) {
            if (is_array($value)
                && isset($merged[$key])
                && is_array($merged[$key])
            ) {
                $merged[$key] = $this->arrayMergeRecursiveDistinct(
                    $merged[$key],
                    $value
                );
            } else {
                $merged[$key] = $value;
            }
        }

        return $merged;
    }

    public function getValue()
    {
        $this->userValue = $this->getDataCoreConfig();

        return $this;
    }

    public function extendValue($extend)
    {
        $this->userValue = $this->arrayMergeRecursiveDistinct(
            $this->userValue,
            $extend
        );

        return $this;
    }

    public function setUserData($value, $path = null)
    {
    }

    /**
     * @param string $string - one of scopes names: stores, websites, default;
     * @return $this;
     */
    public function setScope($string)
    {
        $this->scope = $string;
        return $this;
    }

    /**
     * @param integer $id - one of ids;
     * @return $this
     */
    public function setScopeId($id)
    {
        $this->scopeId = $id;
        return $this;
    }

    public function filterData($data)
    {
        $data = array_map(function ($var) {
            return is_array($var) ? self::filterData($var) : $var;
        }, $data);
        $data = array_filter($data, function ($value) {
            return !empty($value) || $value === false;
        });
        return $data;
    }

    public function isSetKey($array, $key)
    {
        return isset($array[$key]) ? $array[$key] : "";
    }

    /**
     * @param string $storeDomain
     * @param string $settingsPath - for sm store id
     * @return mixed
     */
    public function getSMStoreId($storeDomain = null)
    {
        $path = self::C_PLATFORM_SETTING_PATH . self::C_PATH_TYPE_EVENTS . self::C_LOCATION;
        $id = $this->getConfigItem($path);

        if (empty($id) && $storeDomain == null) {
            return '';
        } elseif ($id == null && $storeDomain != null) {
            return $this->_setSMStoreId($storeDomain);
        }

        return !empty($id) ? $id : '';
    }

    /**
     * Generate and set SALESmanago store identificator based on platform home url;
     * @param string $storeDomain - base Home Url form platform
     * @param string $settingsPath - custom setting path
     * @return boolean
     */
    protected function _setSMStoreId($storeDomain = null, $settingsPath = null)
    {

        if ($storeDomain == null) {
            return false;
        }

        $path = self::C_PLATFORM_SETTING_PATH . self::C_PATH_TYPE_EVENTS . self::C_LOCATION;
        $id = hash('haval128,5', $storeDomain . $this->scopeId . $this->scope);

        $this->setConfigItem($path, $id);

        return $id;
    }
}
