<?php


use Mnv\Core\Config;
use Mnv\Core\DB;
use Mnv\Core\Design;
use Mnv\Core\Helpers\StringHelper;
use Mnv\Core\Locale\i18n;

/**
 * проверяем, что функция mb_ucfirst не объявлена и включено расширение mbstring (Multibyte String Functions)
 */
    if (!function_exists('mb_ucfirst') && extension_loaded('mbstring')) {
        /**
         * mb_ucfirst - преобразует первый символ в верхний регистр
         * @param string $str - строка
         * @param string $encoding - кодировка, по-умолчанию UTF-8
         * @return string
         */
        function mb_ucfirst($str, $encoding = 'UTF-8')
        {
            $str = mb_ereg_replace('^[\ ]+', '', $str);
            $str = mb_strtoupper(mb_substr($str, 0, 1, $encoding), $encoding). mb_substr($str, 1, mb_strlen($str), $encoding);
            return $str;
        }
    }

    function saveSerializations($buildLang = []): bool
    {
        global $smarty, $SECTIONS, $TREE, $CURRENCIES;

        buildSectionArrays($buildLang);
        buildCurrencyArrays();

        $tmpSmarty = Design::init()->design();

        $serializations['TREE']         = improved_var_export($TREE, true);
        $serializations['SECTIONS']     = improved_var_export($SECTIONS, true);
        $serializations['CURRENCIES']   = improved_var_export($CURRENCIES, true);

//        $serializations['TREE'] = var_export($TREE, true);
//        $serializations['SECTIONS'] = var_export($SECTIONS, true);
//        $serializations['CURRENCIES'] = var_export($CURRENCIES, true);
//
        $smarty->assign('TREE', $TREE);
        $smarty->assign('SECTIONS', $SECTIONS);

        $tmpSmarty->assign('serializations', $serializations);
        $tmpSmarty->default_modifiers = array();

        $siteRoot =  empty($buildLang) ? SITE_ROOT : ($buildLang['isDefault'] ? GLOBAL_ROOT : GLOBAL_ROOT . '/' . $buildLang['codename']);

        $fh = fopen($siteRoot . '/includes/serializations.inc.php', 'w');
        if ($fh) {
            fwrite($fh, $tmpSmarty->fetch(GLOBAL_ROOT . '/admin/templates/serializations.tpl', '', 'admin'));
            fclose($fh);
            return true;
        }

        return false;
    }

    function buildSectionArrays($buildLang = []): bool
    {
        global $SECTIONS, $TREE;

        /* section path */
//        $SECTION_PATH = empty($buildLang) ? SITE_URL : ($buildLang->isDefault ? GLOBAL_URL : GLOBAL_URL.'/'.$buildLang->codename);
        $SECTION_PATH = empty($buildLang) ? '' : ($buildLang['isDefault'] ? '' : '/'.$buildLang['codename']);

        /* retrieve all sections */
        $SECTIONS = connect()->table('sections')->orderBy('parentId, sortOrder')->indexKey('sectionId')->getAllIndexes('array');
        /* find all parent sections */
        foreach ($SECTIONS as $sectionId => $section) {
            $SECTIONS[$sectionId]['parents'] = array_reverse(getAllParents($sectionId));
            $SECTIONS[$sectionId]['childLevels'] = 0;
            unset($SECTIONS[$sectionId]['content'], $SECTIONS[$sectionId]['addedBy'], $SECTIONS[$sectionId]['addedOn'], $SECTIONS[$sectionId]['modifiedBy'], $SECTIONS[$sectionId]['modifiedOn']);
            /* section level */
            $SECTIONS[$sectionId]['level'] = count($SECTIONS[$sectionId]['parents']) + 1;
        }

        foreach ($SECTIONS as $sectionId => $section) {

            $SECTIONS[$sectionId]['path'] = $SECTION_PATH;
            if (!empty($section['parents'])) {
                /* find child sections */
                $SECTIONS[$section['parents'][(count($section['parents'])-1)]]['children'][] = $sectionId;

                /* find all child sections (including children of children) */
                /* build path and url */
                /* count child levels */
                foreach ($section['parents'] as $parentId) {

                    /* if templateName is empty, look through parents for subTemplateName */
                    if(empty($section['templateName']) && !empty($SECTIONS[$parentId]['subTemplateName'])){
                        $section['templateName'] = $SECTIONS[$sectionId]['templateName'] = $SECTIONS[$parentId]['subTemplateName'];
                    }

                    /* if subTemplateName is empty, look through parents for subTemplateName */
                    if(empty($section['subTemplateName']) && !empty($SECTIONS[$parentId]['subTemplateName'])){
                        $section['subTemplateName'] = $SECTIONS[$sectionId]['subTemplateName'] = $SECTIONS[$parentId]['subTemplateName'];
                    }

                    /* if artTemplateName is empty, look through parents for artTemplateName */
                    if(empty($section['artTemplateName']) && !empty($SECTIONS[$parentId]['artTemplateName'])){
                        $section['artTemplateName'] = $SECTIONS[$sectionId]['artTemplateName'] = $SECTIONS[$parentId]['artTemplateName'];
                    }

                    /* if isCached is 0 (use default), look through parents for subIsCached */
                    if($section['isCached'] == 0 && $SECTIONS[$parentId]['subIsCached'] != 0){
                        if($SECTIONS[$parentId]['subIsCached'] == 1){
                            $section['isCached']    = $SECTIONS[$sectionId]['isCached']    = $SECTIONS[$parentId]['subIsCached'];
                            $section['cacheTime']   = $SECTIONS[$sectionId]['cacheTime']   = $SECTIONS[$parentId]['subCacheTime'];
                            $section['cachePeriod'] = $SECTIONS[$sectionId]['cachePeriod'] = $SECTIONS[$parentId]['subCachePeriod'];
                        } elseif($SECTIONS[$parentId]['subIsCached'] == -1) {
                            $section['isCached'] = $SECTIONS[$sectionId]['isCached'] = -1;
                        }
                    }

                    /* if artIsCached is 0 (use default), look through parents for artIsCached */
                    if($section['artIsCached'] == 0 && $SECTIONS[$parentId]['artIsCached'] != 0){
                        if($SECTIONS[$parentId]['artIsCached'] == 1){
                            $section['artIsCached']    = $SECTIONS[$sectionId]['artIsCached']    = $SECTIONS[$parentId]['artIsCached'];
                            $section['artCacheTime']   = $SECTIONS[$sectionId]['artCacheTime']   = $SECTIONS[$parentId]['artCacheTime'];
                            $section['artCachePeriod'] = $SECTIONS[$sectionId]['artCachePeriod'] = $SECTIONS[$parentId]['artCachePeriod'];
                        } elseif($SECTIONS[$parentId]['artIsCached'] == -1) {
                            $section['artIsCached'] = $SECTIONS[$sectionId]['artIsCached'] = -1;
                        }
                    }
                    /* if commentsEnabled is 0 (use default), look through parents for subCommentsEnabled */
                    if ($section['commentsEnabled'] == 0 && $SECTIONS[$parentId]['subCommentsEnabled'] != 0) {
                        if($SECTIONS[$parentId]['subCommentsEnabled'] == 1){
                            $section['commentsEnabled'] = $SECTIONS[$sectionId]['commentsEnabled'] = $SECTIONS[$parentId]['subCommentsEnabled'];
                        } else if ($SECTIONS[$parentId]['subCommentsEnabled'] == -1) {
                            $section['commentsEnabled'] = $SECTIONS[$sectionId]['commentsEnabled'] = -1;
                        }
                    }

                    $SECTIONS[$parentId]['allChildren'][] = $sectionId;
                    $SECTIONS[$sectionId]['path'] .= '/'. $SECTIONS[$parentId]['fileName'];
                    if (empty($SECTIONS[$sectionId]['dir'])) {
                        $SECTIONS[$sectionId]['dir'] = $SECTIONS[$parentId]['fileName'];
                    } else {
                        $SECTIONS[$sectionId]['dir'] .= '/' . $SECTIONS[$parentId]['fileName'];
                    }
                    if ($SECTIONS[$parentId]['childLevels'] < ($section['level'] - $SECTIONS[$parentId]['level'])) {
                        $SECTIONS[$parentId]['childLevels'] = $section['level'] - $SECTIONS[$parentId]['level'];
                    }
                }
            }

            if (empty($SECTIONS[$sectionId]['dir'])) {
                $SECTIONS[$sectionId]['dir'] = $section['fileName'];
            } else {
                $SECTIONS[$sectionId]['dir'] .= '/'. $section['fileName'];
            }
            $SECTIONS[$sectionId]['path'] .= '/'. $section['fileName'];

            if ($section['type'] == 'plain') {
                if ($section['fileName'] == 'index') {
                    $tmpUrl = $SECTION_PATH . '/';
                } else {
                    $tmpUrl = $SECTIONS[$sectionId]['path'] . '.' . Config::getValue('file_extension');
                }
            } else {
                $tmpUrl = $SECTIONS[$sectionId]['path'] . '/';
            }

            if ($SECTIONS[$sectionId]['url'] != $tmpUrl) {
                $SECTIONS[$sectionId]['url'] = $tmpUrl;

                connect()->table('sections')->where('sectionId', $sectionId)->update([ 'url'=> $tmpUrl ]);
                connect()->table('articles')->where('sectionId', $sectionId)->updateConcat("url", "CONCAT('" . $SECTIONS[$sectionId]['path'] . "', '/', fileName, '.". Config::getValue('file_extension')."')");
                connect()->table('products')->where('sectionId', $sectionId)->updateConcat("url", "CONCAT('" . $SECTIONS[$sectionId]['path'] . "', '/', fileName, '.". Config::getValue('file_extension')."')");

            }
        }


        /* building section tree */;
        $links = array();
        $TREE = $SECTIONS;
        foreach ($TREE as $sectionId => $section) {
            $links[$sectionId] = &$TREE[$sectionId];
        }
//        print_r($TREE);
        foreach ($TREE as $sectionId => $section) {
            if (empty($section['hasSubsections'])) {
                $links[$sectionId]['hasSubsections'] = false;
            }
            if ($section['parentId'] > 0) {
                $links[$section['parentId']]['hasSubsections'] = true;
                $links[$section['parentId']]['subsections'][] = $TREE[$sectionId];
                $links[$sectionId] = &$links[$section['parentId']]['subsections'][count($links[$section['parentId']]['subsections']) - 1];
                unset($TREE[$sectionId]);
            }
        }

        /** рекурсивно сортировать Tree по sortOrder */
        usort($TREE, 'sortBySortOrder');
        /** сортировать SECTIONS по порядку TREE */
        $newSections = array();
        sortAllSections($TREE, $newSections);
        $SECTIONS = $newSections;
//        print_r($SECTIONS);
        return true;
    }

    /**
     * @param array $sections
     * @param $newSections
     */
    function sortAllSections(array $sections, &$newSections)
    {
        global $SECTIONS;

        foreach ($sections as $section) {
            $newSections[$section['sectionId']] = $SECTIONS[$section['sectionId']];
            if (!empty($section['subsections'])) {
                sortAllSections($section['subsections'], $newSections);
            }
        }
    }

    function getAllParents(int $sectionId, ?array $parents = [])
    {
        global $SECTIONS;

        if ($SECTIONS[$sectionId]['parentId'] > 0) {
            $parents[] = $SECTIONS[$sectionId]['parentId'];
            $parents = getAllParents($SECTIONS[$sectionId]['parentId'], $parents);
        }
        return $parents;
    }

    function sortBySortOrder(&$a, &$b): int
    {
        if (!empty($a['subsections'])) {
            usort($a['subsections'], 'sortBySortOrder');
        }
        if (!empty($b['subsections'])) {
            usort($b['subsections'], 'sortBySortOrder');
        }

        if ($a == $b) {
            return 0;
        }

        return ($a['sortOrder'] < $b['sortOrder']) ? -1 : 1;
    }


    /**
     * Формирование htaccess
     * @param $buildLang
     * @return bool
     */
    function writeHtaccess($buildLang = []): bool
    {
        global $smarty, $SECTIONS;

        $rewrite = md5(rand() * time());

        $tmpSmarty = Design::init()->design();
        $tmpSmarty->setTemplateDir($smarty->defaultAdminTemplateDir());
        $tmpSmarty->setCacheDir($smarty->tmpPath() . 'cache');
        $tmpSmarty->setCompileDir($smarty->tmpPath() . 'compile');
        $tmpSmarty->setCompileId('admin-' . Config::getValue('admin_language'));
        $tmpSmarty->default_modifiers = array('escape');

        $smartyTemplateVars = $smarty->getTemplateVars();
        foreach ($smartyTemplateVars as $key => $value) {
            $tmpSmarty->assign($key, $value);
        }

        $tmpSmarty->assign('rewrite', $rewrite);
        /* find home page */
        foreach ($SECTIONS as $section) {
            if (empty($homePageId)) {
                $homePageId = $section['sectionId'];
            }
            if ($section['fileName'] == 'index') {
                $homePageId = $section['sectionId'];
            }
        }
        if ( ! empty($homePageId) ) {
            $tmpSmarty->assign('homePageId', $homePageId);
        }

        if (empty($buildLang)) {
            $siteRoot    = SITE_ROOT;
            $htaccessTPL = (SITE_LANG == '' ? 'htaccess.tpl' : 'htaccess-ml.tpl');
        } else {

            $tmpSmarty->assign('SITE_LANG', $buildLang['codename']);
            $siteRoot    = ($buildLang['isDefault'] ? GLOBAL_ROOT : GLOBAL_ROOT.'/'.$buildLang['codename']);
            $htaccessTPL = ($buildLang['isDefault'] ? 'htaccess.tpl' : 'htaccess-ml.tpl');
        }

        $htaccess = $tmpSmarty->fetch(GLOBAL_ROOT . '/admin/templates/' . $htaccessTPL);

        if ( $fh = fopen($siteRoot.'/.htaccess', 'w') ) {
            fwrite($fh, $htaccess);
            fclose($fh);

            /* saving seed */
            $setting['codename'] = 'rewrite';
            $setting['value'] = $rewrite;

            connect()->table('settings')->replace($setting);

            unset($tmpSmarty);
            return true;
        }

        return false;
    }

    function buildCurrencyArrays() {
        global $CURRENCIES;

        $CURRENCIES = connect()->table('shop_currency')->getAll('array');
    }


    /** Language */
    function getLanguages(): array
    {
        $languages = array();

        $dh = opendir(GLOBAL_ROOT.'/admin/languages');
        while ($item = readdir($dh)) {
            if ($item != '.' && $item != '..' && $item != '.DS_Store' && is_file(GLOBAL_ROOT . "/admin/languages/$item")) {
                $L = include(GLOBAL_ROOT . "/admin/languages/$item");
                $languages[$L['codeName']] = text2unicode($L['langName'], $L['charset']);
            }
        }
        closedir($dh);

        return array_reverse($languages);
    }


    /**
     * @param $date
     * @return array|string
     */
    function langDate($date)
    {
        global $L;
        $date = strtr($date, $L['dates']);
        return array2unicode($date);
    }


    /**
     * @param string $tag
     * @param string|null $default
     * @return int
     */
    function langLen(string $tag, ?string $default = ''): int
    {
        $text = getTagVal($tag, $default);
        return strlen($text);
    }

    /**
     * @param string $tag
     * @param string|null $default
     * @return array|string
     */
    function langJs(string $tag, ?string $default = '') {
        $text = getTagVal($tag, $default);
        return array2js($text);
    }

    /**
     * @param string $tag
     * @param string|null $default
     * @return array|string
     */
    function lang(string $tag, ?string $default = '') {
        $text = getTagVal($tag, $default);
        return array2unicode($text);
    }

    /**
     * @param $source
     * @return null|string|string[]
     */
    function replaceLanguageTags($source) {
        global $adminLang, $L;
        if ( !isset($L) ) loadLanguage($adminLang);
        return preg_replace_callback('/{([0-9a-zA-Z_\-:]+?)}/', '_replace_lang_tags_callback', $source);
    }

    /**
     * @param $matches
     * @return array|string
     */
    function _replace_lang_tags_callback($matches) {
        $text = getTagVal($matches[1], $matches[0]);
        return array2unicode($text);
    }

    /**
     * @param $tag
     * @param $default
     * @return mixed
     */
    function getTagVal($tag, $default) {
        global $L;

        $result = '';
        $keys = explode(':', $tag);
        switch (count($keys)) {
            case 1:
                $result = $L[$keys[0]] ?? $default;
                break;
            case 2:
                $result = $L[$keys[0]][$keys[1]] ?? $default;
                break;
            case 3:
                $result = $L[$keys[0]][$keys[1]][$keys[2]] ?? $default;
                break;
            case 4:
                $result = $L[$keys[0]][$keys[1]][$keys[2]][$keys[3]] ?? $default;
                break;
        }

        return $result;
    }

    /**
     * @param $var
     * @return array|string
     */
    function array2js($var) {
        global $L;

        if (is_array($var)) {
            return array_map('array2js', $var);
        }

        return text2js($var, $L['charset']);
    }

    /**
     * @param $text
     * @param $encoding
     * @return string
     */
    function text2js($text, $encoding): string
    {
        return text2unicode($text, $encoding);
    }

    /**
     * @param $var
     * @return array|string
     */
    function array2unicode($var) {
        global $L;

        if (is_array($var)) {
            return array_map('array2unicode', $var);
        }

        return text2unicode($var, $L['charset']);
    }

    /**
     * @param $text
     * @param $encoding
     * @return string
     */
    function text2unicode($text, $encoding): string
    {
        mb_internal_encoding('UTF-8');
        return mb_convert_encoding($text, 'UTF-8', $encoding);
    }

    /**
     * @param $language
     */
    function loadLanguage($language) {
        global $L;

        if (is_file(GLOBAL_ROOT.'/admin/languages/'.$language.'.inc.php')) {
            $L = include(GLOBAL_ROOT.'/admin/languages/'.$language.'.inc.php');
        } else {
            $L = include(GLOBAL_ROOT . '/admin/languages/ru.inc.php');
        }
    }
    /** END Language */

	/**
     * @method gmNow
     * @return false|string
     */
    function gmNow() {
        return gmdate('Y-m-d H:i:s');
    }

    function htmlspecialcharsbx($string, $flags = ENT_COMPAT, $doubleEncode = true)
    {
        //function for php 5.4 where default encoding is UTF-8
        return htmlspecialchars($string, $flags, (defined("BX_UTF") ? "UTF-8" : "ISO-8859-1"), $doubleEncode);
    }

    function htmlspecialcharsEx($str)
    {
        static $search =  array("&amp;",     "&lt;",     "&gt;",     "&quot;",     "&#34;",     "&#x22;",     "&#39;",     "&#x27;",     "<",    ">",    "\"");
        static $replace = array("&amp;amp;", "&amp;lt;", "&amp;gt;", "&amp;quot;", "&amp;#34;", "&amp;#x22;", "&amp;#39;", "&amp;#x27;", "&lt;", "&gt;", "&quot;");

        return StringHelper::str_replace($search, $replace, $str);
    }

    function htmlspecialcharsback($str)
    {
        static $search =  array("&lt;", "&gt;", "&quot;", "&apos;", "&amp;");
        static $replace = array("<",    ">",    "\"",     "'",      "&");

        return StringHelper::str_replace($search, $replace, $str);
    }

	/**
	 * @param $variable
	 * @param bool|false $return
	 * @return string|null
	 */
	function improved_var_export($variable, bool $return = false): ?string
    {
		if ($variable instanceof stdClass) {
			$result = '(object) ' . improved_var_export(get_object_vars($variable), true);
		} else if (is_array($variable)) {
			$array = array();
			foreach ($variable as $key => $value) {
				$array[] = var_export($key, true) . ' => ' . improved_var_export($value, true);
			}
			$result = 'array(' . implode(', ', $array) . ')';
		} else {
			$result = var_export($variable, true);
		}

		if (!$return) {
			print $result;
			return null;
		}

        return $result;
    }

    
    /**
     * @param $path
     * @param string $pattern
     * @return array
     */
    function searchDir($path, $pattern = '*.*')
	{
    	$files = array();
    	$dh = opendir($path);
    	$pattern = preg_quote($pattern);
    	$pattern = str_replace('\\*', '.*?', $pattern);
    	while($file = readdir($dh)) if(preg_match("/^$pattern$/i", $file) && $file != '.' && $file != '..') $files[] = $file;
    	sort($files);
    	closedir($dh);
    	return $files;
    }

    
    /**
     * @param $referer
     * @return array
     */
    function parseReferer($referer)
	{

       	$result = array();

    	if (preg_match('|^http|i', $referer)) {
            $result['refererUrl'] = $referer;
        }
    	if (preg_match('|^http://(www\.)?([^/]+)/.*|i', $referer, $matches)) {
            $result['refererWebsite'] = $matches[2];
        }
    	if (preg_match("/^http.+[\?\&](" . Config::getValue('query_fields') . ")=([^\&]+).*/i", $referer, $matches)){
    		$result['searchPhrase'] = urldecode($matches[2]);
    		if (function_exists('mb_detect_order')) {
    			mb_detect_order("UTF-8, " . Config::getValue('charset') . ", ASCII");
    			$encoding = mb_detect_encoding($result['searchPhrase']);
    			$result['searchPhrase'] = ($encoding == 'UTF-8') ? mb_convert_encoding($result['searchPhrase'], Config::getValue('charset'), $encoding) : $result['searchPhrase'];
    		}
    	}
//    	print_r($result);
    	return $result;
    }


?>	