<?php

namespace App\Core;

class Theme {
    /**
     * Class init state.
     *
     * @var boolean
    */
    public static $initialized = false;

    /**
     * Theme's actual config.
     *
     * @var array
    */
    public static $config;

    /**
     * Theme execution mode(dev, preview, export, release)
     *
     * @var string
    */
    public static $viewMode;

    /**
     * Theme name
     *
     * @var string
    */
    public static $name;

    /**
     * Demo name
     *
     * @var string
    */
    public static $demo;

    /**
     * Product name
     *
     * @var string
    */
    public static $product;

    /**
     * Current page's path
     *
     * @var string
    */
    public static $page = 'index';

    public static $htmlAttributes;

    public static $htmlClasses;

    public static $cssVariables;

    // Page layout variables
    public static $pageLayoutPath;
    public static $pageLayoutView;
    public static $pageLayoutParams;

    // Imported modals
    public static $importedModals = array();

    // Free version flag

    public static $freeVersion = false;

    /**
     * Class constructor.
     *
    */
    public static function init($theme, $demo = '') {
        global $_COMMON_PATH, $_THEME_PATH;

        if (self::$initialized) {
            return;
        }

        // Set theme name
        self::$name = $theme;
        self::$demo = $demo;

        // Get the current theme config
        $theme_config = include $_THEME_PATH . '/dist/config/general.php';

        // Init theme general config so some parameters will be available within theme menu and page configs
        self::$config = $theme_config;

        // Get common config
        $common_config = include $_COMMON_PATH . '/dist/config/general.php';

        // Merge the config arrays
        self::$config = array_replace_recursive($common_config, $theme_config);

        // Do not merge common pages and menus for server side docs intances
        if ( empty(self::$product) ) {
            $common_config['pages'] = include $_COMMON_PATH . '/dist/config/pages.php';
            $common_config['menu'] = include $_COMMON_PATH . '/dist/config/menu.php';

            // Global menu config
            self::$config['menu']['global'] = $common_config['menu']['global'];
        }

        // Local menu and pages config
        $theme_config['menu'] = include $_THEME_PATH . '/dist/config/menu.php';
        $theme_config['pages'] = include $_THEME_PATH . '/dist/config/pages.php';

        // For multi demo, merge demo1 menu config with current demo
        if (self::$demo != '' && self::$demo != 'demo1') {
            $demo1_actual_path = str_replace(self::$demo, 'demo1/', $_THEME_PATH);
            $demo1_general_config = include $demo1_actual_path . '/dist/config/general.php';
            $demo1_menu_config = include $demo1_actual_path . '/dist/config/menu.php';
            $demo1_pages_config = include $demo1_actual_path . '/dist/config/pages.php';

            $common_config['product'] = array_replace_recursive($common_config['product'], $demo1_general_config['product']);
            $common_config['meta'] = array_replace_recursive($common_config['meta'], $demo1_general_config['meta']);
            $theme_config['menu'] = array_replace_recursive($demo1_menu_config, $theme_config['menu']);
            $theme_config['pages'] = array_replace_recursive($demo1_pages_config, $theme_config['pages']);
        }

        // Server side docs integration
        if ( !empty(self::$product) && isset(self::$config['products']) && isset(self::$config['products'][self::$product]) ) {
            $theme_config['product'] = $theme_config['products'][self::$product];
            $theme_config['layout']['docs']['logo'] = $theme_config['layout']['docs']['logo'][self::$product];
            $theme_config['assets']['favicon'] = $theme_config['assets']['favicon'][self::$product];
        }

        // Merge the config arrays
        self::$config = array_replace_recursive($common_config, $theme_config);

        // Check option to enable pretty URL
        if (empty($_SERVER['QUERY_STRING']) && self::getOption('pretty-url')) {
            $_REQUEST['type'] = 'html';
        }

        // Set initialized
        self::$initialized = true;
    }

    /**
     * Handle requests.
     *
     * @param string $theme The theme name.
     * @param string $demo The theme's demo name.
    */
    public static function run() {
        LayoutBuilder::init();

        if (isset($_REQUEST['layout-marker']) && $_REQUEST['layout-marker']) {
            self::setViewMode('export');
        }

        if (isset($_POST['layout-builder']) || isset($_REQUEST['download'])) {
            LayoutBuilder::process();
            echo "OK";
        } else {
            self::handlePage();
        }
    }

    /**
     * Handle page requests.
     *
     * @param string $theme The theme name.
     * @param string $demo The theme's demo name.
    */
    public static function handlePage() {
        // Setup current page path
        if (isset($_REQUEST['page'])) {
            self::$page = $_REQUEST['page'];
            // Remove first and last slashes
            self::$page = trim( self::$page, "/" );
            self::$page = rtrim( self::$page, "/" );
        }

        // Lookup for an index page config
        if (Util::hasArrayValue(self::$config['pages'], self::$page . '/index') == true) {
            self::$page = self::$page . '/index';
        }

        // Lookup for page config
        if (Util::hasArrayValue(self::$config['pages'], self::$page)) {
            self::$config['page'] = Util::getArrayValue(self::$config['pages'], self::$page);
        } else {
            echo 'Page not found: ' . self::$page;
            exit;
        }

        // Override wildcard layout config
        $page_group_options = self::getPageGroupOptions(self::$config['pages'], self::$page);
        if ($page_group_options) {
            self::$config['page'] = Util::arrayMergeRecursive($page_group_options, self::$config['page']);
        }

        // Merge Layout Builder Stored Options
        if (LayoutBuilder::hasOptions()) {
            self::$config['layout'] = array_replace_recursive(self::$config['layout'], LayoutBuilder::getOptions());
        }

        // Override page layout config
        if (isset(self::$config['page']['layout'])) {
            self::$config['layout'] = array_replace_recursive(self::$config['layout'], self::$config['page']['layout']);
        }

        // Override page layout config
        if (isset(self::$config['page']['widgets'])) {
            self::$config['widgets'] = array_replace_recursive(self::$config['widgets'], self::$config['page']['widgets']);
        }

        // Override page meta config
        if (isset(self::$config['page']['meta'])) {
            self::$config['meta'] = array_replace_recursive(self::$config['meta'], self::$config['page']['meta']);
        }

        // Recursive layout array boolean value format
        array_walk_recursive(
            self::$config['layout'],
            function (&$value, $key) {
                if (strpos($key, "data-kt-") !== false) {
                    return;
                }

                if ($value === 'true') {
                    $value = true;
                } elseif ($value === 'false') {
                    $value = false;
                }
            }
        );

        // Run Layout Bootstrap
        Bootstrap::run();

        // Generate Page
        ob_start(array(Util::class, 'tidyHtml'));

        if (self::getOption("layout", "main/type") == 'none') {
            Theme::getPageView();  // empty layout
        } else {
            self::getCommonView('base'); // normal layout
        }

        ob_end_flush();
    }

    /**
     * Sets the theme's mode.
     *
     * @param string $value the theme's mode(preview, release).
    */
    public static function setViewMode($value) {
        // force preview mode on server
        if (isset($_SERVER['SERVER_NAME']) && strpos($_SERVER['SERVER_NAME'], 'keenthemes.com') !== false) {
            self::$viewMode = 'preview';
        } elseif (isset($_REQUEST['viewMode']) && $_REQUEST['viewMode'] === 'release') {
            self::$viewMode = 'release';
        } else {
            self::$viewMode = $value;
        }
    }

    public static function setProduct($product) {
        self::$product = $product;
    }

    public static function getProduct() {
        return self::$product;
    }

    public static function isFrameworkDocsMode() {
        return !empty(self::$product);
    }

    public static function isFrameworkStarterkitAvailable() {
        $frameworks = Theme::getOption("general", "frameworks");

        foreach( $frameworks as $name => $framework ) {
            if ( isset($framework["themes"][self::getName()]) ) {
                return true;
            }
        }

        return false;
    }

    public static function getViewMode() {
        return self::$viewMode;
    }

    public static function getName() {
        return self::$name;
    }

    public static function getDemo() {
        return self::$demo;
    }

    public static function getDemosTotal() {
        $total = 0;

        foreach(Theme::getOption('product', 'demos') as $id => $demo) {
            if ($demo['published'] === true) {
                $total++;
            }
        }

        return $total;
    }

    public static function isMultiDemo() {
        return !empty(self::getDemo());
    }

    public static function hasWebpack() {
        return !(isset($_REQUEST['webpack']) && !filter_var($_REQUEST['webpack'], FILTER_VALIDATE_BOOLEAN));
    }

    public static function isFreeVersion() {
        if (isset($_REQUEST['free'])) {
            return filter_var($_REQUEST['free'], FILTER_VALIDATE_BOOLEAN);
        }

        return self::$freeVersion;
    }

    public static function setFreeVersion($flag) {
        return self::$freeVersion = $flag;
    }

    public static function putProVersionTooltip($attr = array()) {
        $attr['data-bs-toggle'] = 'tooltip';
        $attr['title'] = "Available in <span class='badge badge-pro badge-light-danger fw-bold fs-9 px-2 py-1 ms-1'>Pro</span> version";
        $attr['data-bs-html'] = 'true';

        if (empty($attr) || isset($attr['data-bs-placement']) === false) {
            $attr['data-bs-placement'] = 'bottom';
        }

        if (Theme::isFreeVersion() === true) {
            echo Util::putHtmlAttributes($attr);
        }
    }

    public static function getOption($scope, $path = false, $default = null) {
        if (!self::hasOption($scope, $path)) {
            return $default;
        }

        $result = array();

        if (!isset(self::$config[$scope])) {
            return null;
        }

        if ($path === false) {
            $result = self::$config[$scope];
        } else {
            $result = Util::getArrayValue(self::$config[$scope], $path);
        }

        // check if its a callback
        if (is_callable($result) && !is_string($result)) {
            $result = call_user_func($result);
        }

        return $result;
    }

    public static function setOption($scope, $path, $value) {
        if (isset(self::$config[$scope])) {
            return Util::setArrayValue(self::$config[$scope], $path, $value);
        } else {
            return false;
        }
    }

    public static function hasOption($scope, $path = false) {
        if (isset(self::$config[$scope])) {
            if ($path === false) {
                return isset(self::$config[$scope]);
            } else {
                return Util::hasArrayValue(self::$config[$scope], $path);
            }
        } else {
            return false;
        }
    }

    public static function getPageGroupOptions($pagesConfig, $pagePath) {
        $parts = explode('/', $pagePath);
        $running = count($parts) - 1;

        for ($i = 0; $i <= count($parts); $i++) {
            $path = array();

            for ($j = 0; $j <= $running; $j++) {
                $path[] = $parts[$j];
            }

            $running--;
            $path = implode('/', $path);
            $path = $path . '/*';

            if ( Util::hasArrayValue($pagesConfig, $path) ) {
                return Util::getArrayValue($pagesConfig, $path);
            }
        }

        return false;
    }

    public static function getPageOptionsByPath($path) {
        if (Util::hasArrayValue(self::$config['pages'], $path)) {
            return Util::getArrayValue(self::$config['pages'], $path);
        } else {
            return false;
        }
    }

    public static function getVendorFiles($type) {
        $files = array();
        $vendors = Theme::getOption('vendors');

        $globalVendors = Theme::getOption('assets', 'vendors');
        $pageVendors = Theme::getOption('page', 'assets/vendors');

        if ($globalVendors && count($globalVendors) > 0) {
            foreach($globalVendors as $name) {
                if (isset($vendors[$name]) && is_array($vendors[$name]) && isset($vendors[$name][$type])) {
                    foreach($vendors[$name][$type] as $each) {
                        $files[] = $each;
                    }
                }
            }
        }

        if ($pageVendors && count($pageVendors) > 0) {
            foreach($pageVendors as $name) {
                if (isset($vendors[$name]) && is_array($vendors[$name]) && isset($vendors[$name][$type])) {
                    foreach($vendors[$name][$type] as $each) {
                        $files[] = $each;
                    }
                }
            }
        }

        return array_unique($files);
    }

    public static function hasVendorFiles($type) {
        return count(self::getVendorFiles($type)) > 0;
    }

    public static function isProPage($path) {
        $pageConfig = self::getPageOptionsByPath($path);

        if ($pageConfig && isset($pageConfig['pro']) && $pageConfig['pro'] === true) {
            return true;
        } else {
            return false;
        }
    }

    public static function checkPageByPath($path) {
        $pageConfig = self::getPageOptionsByPath($path);

        if ($pageConfig) {
            return true;
        } else {
            return false;
        }
    }

    public static function isExclusivePage($path) {
        $pageConfig = self::getPageOptionsByPath($path);

        if ($pageConfig && isset($pageConfig['exclusive']) && $pageConfig['exclusive'] === true) {
            return true;
        } else {
            return false;
        }
    }

    public static function getPageKey() {
        $el = (array)explode('/', self::getPagePath());

        return end($el);
    }

    public static function getPagePath() {
        return self::$page;
    }

    public static function getPagePathPart($index) {
        $parts = explode('/', self::$page);

        return isset($parts[$index]) ? $parts[$index] : false;
    }

    public static function addHtmlAttribute($scope, $name, $value) {
        self::$htmlAttributes[$scope][$name] = $value;
    }

    public static function addHtmlAttributes($scope, $attributes) {
        foreach ($attributes as $key => $value) {
            self::$htmlAttributes[$scope][$key] = $value;
        }
    }

    public static function addHtmlClass($scope, $class) {
        self::$htmlClasses[$scope][] = $class;
    }

    public static function addCssVariable($scope, $name, $value) {
        self::$cssVariables[$scope][$name] = $value;
    }

    public static function printHtmlAttributes($scope) {
        $Attributes = array();

        if (isset(self::$htmlAttributes[$scope]) && !empty(self::$htmlAttributes[$scope])) {
            echo  Util::getHtmlAttributes(self::$htmlAttributes[$scope]);
        }

        echo '';
    }

    public static function printHtmlClasses($scope, $full = true) {
        if (isset(self::$htmlClasses[$scope]) && !empty(self::$htmlClasses[$scope])) {
            $classes = implode(' ', self::$htmlClasses[$scope]);

            if ($full) {
                echo  Util::getHtmlClass(self::$htmlClasses[$scope]);
            } else {
                echo  Util::getHtmlClass(self::$htmlClasses[$scope], false);
            }
        } else {
            echo '';
        }
    }

    public static function printCssVariables($scope) {
        $Attributes = array();

        if (isset(self::$cssVariables[$scope]) && !empty(self::$cssVariables[$scope])) {
            echo  Util::getCssVariables(self::$cssVariables[$scope]);
        }
    }

    public static function appendVersionToUrl($path) {
        // only at preview version
        if (self::$viewMode == 'preview') {
            $path .= '?v=' . self::getOption('theme/version');
        }

        return $path;
    }

    public static function getView($path, $params = array(), $once = false, $createPartialFileInExport = true) {
        global $_THEME_PATH, $_COMMON_PATH;

        $actual_path = $_THEME_PATH . '/dist/view/' . $path . '.php';
        $common_path = $_COMMON_PATH . '/dist/view/' . $path . '.php';

        // For multi demo, include from demo1 for other demos
        if ( file_exists($actual_path) === false ) {
            if (self::$demo != '' && self::$demo != 'demo1') {
                $actual_path = str_replace(self::$demo . '/', 'demo1/', $actual_path);
            }
        }

        // Get view from common(core))
        if ( file_exists($actual_path) === false && file_exists($common_path) === true ) {  // try to find in common
            $actual_path = $common_path;
        }

        // Override widget params
        if (self::hasOption('widgets')) {
            $widgets = self::getOption('widgets');

            if (isset($widgets[$path]) && isset($widgets[$path]['params'])) {
                $params = array_replace_recursive($params, $widgets[$path]['params']);
            }
        }

        // Include view
        self::includeView($actual_path, $params, $once, $createPartialFileInExport);
    }

    public static function getRootView($path, $params = array(), $once = false) {
        self::getView($path, $params, $once, false);
    }

    public static function getPageView($params = array()) {
        global $_THEME_PATH, $_COMMON_PATH;

        $actual_path = $_THEME_PATH . '/dist/view/pages/' . self::$config['page']['view'] . '.php';
        $common_path = $_COMMON_PATH . '/dist/view/pages/' . self::$config['page']['view'] . '.php';

        // For multi demo, include from demo1 for other demos
        if ( file_exists($actual_path) === false ) {
            if (self::$demo != '' && self::$demo != 'demo1') {
                $actual_path = str_replace(self::$demo . '/', 'demo1/', $actual_path);
            }
        }

        if ( file_exists($actual_path) === false && file_exists($common_path) === true ) {  // try to find in common
            $actual_path = $common_path;
        }

        self::includeView($actual_path, $params);
    }

    public static function getCommonView($path, $params = array()) {
        global $_COMMON_PATH;

        $actual_path = $_COMMON_PATH . '/dist/view/' . $path . '.php';

        self::includeView($actual_path, $params);
    }

    public static function includeView($path, $params = array(), $once = false, $createPartialFileInExport = true) {
        if (!file_exists($path)) {
            echo '"' . $path . '" does not exist!<br>';
            return;
        }

        if (isset($_REQUEST['layout-marker']) && $createPartialFileInExport) {
            preg_match('/dist\/view\/(.*?)\.php$/', $path, $matches);
            if ( ! empty($matches)) {
                echo "\r\n" . '<!--layout-partial-start:'.htmlentities($matches[1]).'-->' . "\r\n";
                if ($once === true) {
                    include_once($path);
                } else {
                    include($path);
                }
                echo "\r\n" . '<!--layout-partial-end:'.htmlentities($matches[1]).'-->' . "\r\n";
            }
        } else {
            if ($once === true) {
                include_once($path);
            } else {
                include($path);
            }
        }

        return $path;
    }

    public static function importModal($name) {
        $modals = self::getOption('modals');

        if (isset($modals[$name]) && isset(self::$importedModals[$name]) === false) {
            self::$importedModals[$name] = $modals[$name];

            if (isset($modals[$name]['assets'])) {
                if (isset($modals[$name]['assets']['vendors'])) {
                    if (isset(self::$config['page']['assets']['vendors'])) {
                        self::$config['page']['assets']['vendors'] = array_merge(self::$config['page']['assets']['vendors'], $modals[$name]['assets']['vendors']);
                    } else {
                        self::$config['page']['assets']['vendors'] = $modals[$name]['assets']['vendors'];
                    }
                }

                if (isset($modals[$name]['assets']['custom'])) {
                    if (isset($modals[$name]['assets']['custom']['js'])) {
                        if (isset(self::$config['page']['assets']['custom']['js'])) {
                            self::$config['page']['assets']['custom']['js'] = array_merge(self::$config['page']['assets']['custom']['js'], $modals[$name]['assets']['custom']['js']);
                        } else {
                            self::$config['page']['assets']['custom']['js'] = $modals[$name]['assets']['custom']['js'];
                        }
                    }

                    if (isset($modals[$name]['assets']['custom']['css'])) {
                        if (isset(self::$config['page']['assets']['custom']['css'])) {
                            self::$config['page']['assets']['custom']['css'] = array_merge(self::$config['page']['assets']['custom']['css'], $modals[$name]['assets']['custom']['css']);
                        } else {
                            self::$config['page']['assets']['custom']['css'] = $modals[$name]['assets']['custom']['css'];
                        }
                    }
                }
            }
        }
    }

    public static function importModalById($id) {
        $name = str_replace('#kt_modal_', '', $id);
        $name = str_replace('_', '-', $name);

        self::importModal($name);
    }

    public static function linkModal($name, $return = false) {
        $modals = self::getOption('modals');

        if ($name && isset($modals[$name])) {
            self::importModal($name);
        } else {
            return;
        }

        $code = ' data-bs-toggle="modal"';
        $code .= ' data-bs-target="#kt_modal_' . str_replace('-', '_', $name) . '"';

        if ($return === true) {
            return $code;
        } else {
            echo $code;
        }
    }

    public static function hasImportedModals() {
        return !empty(self::$importedModals);
    }

    public static function includeImportedModals() {
        foreach(self::$importedModals as $name => $modal) {
            self::getView($modal['view'], (isset($modal['params']) ? $modal['params'] : null), true);
        }
    }

    public static function beginPageLayout($path, $params = array()) {
        self::$pageLayoutPath = $path;
        self::$pageLayoutParams = $params;
        ob_start();
    }

    public static function getPageLayoutView() {
        echo self::$pageLayoutView;
    }

    public static function endPageLayout() {
        self::$pageLayoutView = ob_get_contents();
        ob_end_clean();

        self::getView(self::$pageLayoutPath, self::$pageLayoutParams);
    }

    public static function getAssetsPath() {
        global $_THEME_PATH;

        return $_THEME_PATH . '/dist/assets/';
    }

    public static function getMediaPath() {
        return self::getAssetsPath() . 'media/';
    }

    public static function getBaseUrlPath() {
        if ( ! isset($_SERVER['PHP_SELF'])) {
            return '';
        }

        if (!empty($_SERVER['PHP_SELF'])) {
            return dirname($_SERVER['PHP_SELF']).'/';
        }

        return '';
    }

    public static function getAssetsUrlPath() {
        return self::getBaseUrlPath() . 'assets/';
    }

    public static function getMediaUrlPath($file = '') {
        $file = ltrim($file, '/');
        return self::getAssetsUrlPath() . 'media/' . $file;
    }

    public static function includeFonts($value='') {
        if (self::hasOption('assets', 'fonts/google')) {
            $fonts = self::getOption('assets', 'fonts/google');

            echo '<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=' . implode('|', $fonts) . '"/>';
        }
    }

    public static function rtlCssFilename($path) {
        if ( self::isRTL() === true ) {
            if (strpos($path, 'fullcalendar') !== false) {
            } else {
                $path = str_replace('.css', '.rtl.css', $path);
            }
        }

        return $path;
    }

    public static function isRTL() {
        if ( (isset($_REQUEST['rtl']) && $_REQUEST['rtl'] == 1) || self::getOption('layout', 'app/general/rtl') === true ) {
            return true;
        } else {
            return false;
        }
    }

    public static function strposa($haystack, $needle, $offset = 0) {
        if (!is_array($needle)) {
            $needle = array($needle);
        }
        foreach ($needle as $query) {
            if (strpos($haystack, $query, $offset) !== false) {
                return true;
            } // stop on first true result
        }

        return false;
    }

    /**
     * Check if current theme has dark mode
     *
     * @return bool
     */
    public static function isDarkModeEnabled() {
        if ( self::hasOption('layout', 'app/general/dark-mode-enabled') ) {
            return (bool) self::getOption('layout', 'app/general/dark-mode-enabled');
        }

        return (bool) self::getOption('layout', 'main/dark-mode-enabled');
    }

    /**
     * Get current mode
     *
     * @return mixed|string
     */
    public static function getCurrentMode() {
        if ( self::isDarkModeEnabled() === true ) {
            if ( isset($_REQUEST['mode']) && $_REQUEST['mode'] ) {
                return $_REQUEST['mode'];
            }

            if ( self::hasOption('layout', 'app/general/mode') ) {
                return self::getOption('layout', 'app/general/mode');
            }

            if ( self::getOption('layout', 'main/dark-mode-default') === true ) {
                return "dark";
            }
        }
    }

    /**
     * Check dark mode
     *
     * @return mixed|string
     */
    public static function isDarkMode() {
        return self::getCurrentMode() === 'dark';
    }

    public static function isPageBgWhite() {
        if ( self::hasOption('layout', 'app/general/page-bg-white') ) {
            return (bool) self::getOption('layout', 'app/general/page-bg-white');
        }

        return (bool) self::getOption('layout', 'main/page-bg-white');
    }

    public static function getPageUrl($path, $demo = '', $mode = null) {
        // Disable pro page URL's for the free version
        if (self::isFreeVersion() === true && self::isProPage($path) === true) {
            return "#";
        }

        if ($path === '#') {
            return $path;
        }

        $baseUrl = self::getBaseUrlPath();

        $params = '';
        if (isset($_REQUEST['type']) && $_REQUEST['type'] === 'html') {
            // param keep in url
            if (isset($_REQUEST['rtl']) && $_REQUEST['rtl']) {
                $params = 'rtl/';
            }

            if (!empty($demo)) {
                if (self::getViewMode() === 'release') {
                    // force add link to other demo in release
                    $baseUrl .= '../../'.$demo.'/dist/';
                } else {
                    // for preview
                    $baseUrl .= '../'.$demo.'/'.$params;
                }
            } else {
                $d = '';
                if (!empty(self::getDemo())) {
                    $d = '../'.self::getDemo().'/';
                }
                if (self::getViewMode() === 'release') {
                    // force add link to other demo in release
                    $baseUrl .= '../'.$d.'dist/';
                } else {
                    // for preview
                    $baseUrl .= $d.$params;
                }
            }

            $url = $baseUrl.$path.'.html';

            // skip layout builder page for generated html
            if (strpos($path, 'builder') !== false && self::getViewMode() === 'release') {

                if (!empty(self::getDemo())) {
                    $path = self::getDemo().'/'.$path;
                }

                $url = self::getOption('product', 'preview').'/'.$path.'.html';
            }
        } else {
            if (isset($_REQUEST['rtl']) && $_REQUEST['rtl']) {
                $params = '&rtl=1';
            }

            if (!empty($demo)) {
                // force add link to other demo
                $baseUrl .= '../../'.$demo.'/dist/';
            }

            $url = $baseUrl.'?page='.$path.$params;
        }

        return $url;
    }

    public static function isCurrentPage($path) {
        return self::$page === $path;
    }

    public static function getProductName() {
        if (Theme::isFreeVersion() === true && self::getOption('product', 'name-free')) {
            return self::getOption('product', 'name-free');
        } else if (self::getOption('product', 'name-pro')) {
            return self::getOption('product', 'name-pro');
        } else {
            return self::getOption('product', 'name');
        }
    }

    public static function getProductNameHtml() {
        return '<strong class="text-gray-900">' . self::getProductName() . '</strong>&nbsp;';
    }

    public static function getProductDescription() {
        return self::getOption('product', 'description');
    }

    public static function getSassVariableMap($key) {
        global $_COMMON_PATH;

        // get cache if available
        $variables = Util::getCache(__CLASS__.'-'.__FUNCTION__);

        if (empty($variables)) {
            // get variable scss file content
            $content = file_get_contents($_COMMON_PATH.'/src/sass/components/_variables.scss');

            // regex capture variables with array
            preg_match_all('/\$([A-Za-z0-9-]+): ?\((.*?)\) ?!default;/sm', $content, $matches);

            $variables = array_combine($matches[1], $matches[2]);

            foreach ($variables as &$variable) {
                preg_match_all('/"?([A-Za-z0-9-]+)"? ?:/', $variable, $matched);
                $variable = $matched[1];
            }

            // keep cache in file
            Util::putCache(__CLASS__.'-'.__FUNCTION__, $variables);
        }

        if (isset($variables[$key])) {
            return $variables[$key];
        }

        return null;
    }

    public static function getPackageReferences() {
        global $_COMMON_PATH;

        $content = file_get_contents($_COMMON_PATH.'/tools/package.json');

        $json         = json_decode($content, true);
        $dependencies = $json['dependencies'];

        $references = self::getOption('general', 'references');

        foreach ($dependencies as $plugin => $version) {
            try {
                $json_file = $_COMMON_PATH.'/tools/node_modules/'.$plugin.'/package.json';
                if (!file_exists($json_file)) {
                    continue;
                }
                $plugin_content = file_get_contents($json_file);
                $plugin_json    = json_decode($plugin_content, true);

                $url = '';
                if (isset($plugin_json['homepage'])) {
                    $url = $plugin_json['homepage'];

                } elseif (isset($plugin_json['repository']['url'])) {
                    // if it is a git url convert to normal url
                    $url = preg_replace('/(git)?(\+https)?:\/\/(.*?)\.git$/', 'https://$3', $plugin_json['repository']['url']);

                } elseif (isset($plugin_json['bugs']['url'])) {
                    $url = $plugin_json['bugs']['url'];

                } elseif (isset($plugin_json['funding'])) {
                    $url = $plugin_json['funding'];
                    if (isset($plugin_json['funding']['url'])) {
                        $url = $plugin_json['funding']['url'];
                    }
                }

                if (!empty($url)) {
                    $references[$url] = array(
                        'name'    => $plugin,
                        'url'     => $url,
                        'version' => $plugin_json['version'] ?? '',
                    );
                }
            } catch (Exception $exception) {
            }
        }

        return $references;
    }

    public static function getChangelogInfo() {
        global $_THEME_PATH, $_COMMON_PATH;

        $changelog = array();

        $common_path = $_COMMON_PATH . '/dist/changelog';
        $current_path = $_THEME_PATH . '/dist/changelog';

        // For multi demo, include from demo1 for other demos
        if ( file_exists($current_path) === false ) {
            if (self::$demo != '' && self::$demo != 'demo1') {
                $current_path = str_replace(self::$demo . '/', 'demo1/', $current_path);
            }
        }

        // Read core changelog dir
        if ($handle = @opendir($common_path)) {
            while (false !== ($entry = readdir($handle))) {
                $path = $common_path . '/' . $entry;

                if ($entry != "." && $entry != ".." && file_exists($path)) {
                    $array = include($common_path . '/' . $entry);

                    $changelog = array_replace_recursive($changelog, $array);
                }
            }

            closedir($handle);
        }

        // Read current changelog dir
        if ($handle = @opendir($current_path)) {
            while (false !== ($entry = readdir($handle))) {
                $path = $current_path . '/' . $entry;

                if ($entry != "." && $entry != ".." && file_exists($path)) {
                    $array = include($path);

                    $changelog = array_replace_recursive($changelog, $array);
                }
            }

            closedir($handle);
        }

        // reverse sort by key
        uasort($changelog, function ($a, $b) {
            $a = date_create_from_format('d F, Y', $a['date']);
            $b = date_create_from_format('d F, Y', $b['date']);

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

            return ($a < $b) ? 1 : -1;
        });

        return $changelog;
    }

    public static function getVersion() {
        return self::getOption("product", "version");
    }

    public static function addPageJs($path) {
        self::$config["page"]["assets"]['custom']['js'][] = $path;
    }

    public static function getCorePath() {
        return __DIR__.'/../..';
    }

    public static function getPagesConfig($config, &$result =  array()) {
        foreach($config as $key => $page) {
            if ($key === '*') {
                continue;
            }

            if (isset($page['view']) && (isset($page['title']))) {
                $page['path'] = @$config['path'] . '/' . $key;

                $result[] = $page;
            } else if (is_array($page)) {
                if (isset($config['path'])) {
                    $page['path'] = $config['path'] . '/' . $key;
                } else {
                    $page['path'] = $key;
                }

                self::getPagesConfig($page, $result);
            }
        }

        return $result;
    }

    public static function printJsHostUrl() {
        echo sprintf('var hostUrl = "%s";', self::getAssetsUrlPath());
    }

    public static function getImageDarkUrl($path) {
        $path = str_replace(".svg", "-dark.svg", $path);
        $path = str_replace(".png", "-dark.png", $path);
        $path = str_replace(".jpg", "-dark.jpg", $path);

        $path_dark_path = Theme::getMediaPath() . $path;
        $path_dark_url_path = Theme::getMediaUrlPath() .  $path;

        if (file_exists($path_dark_path)) {
            return $path_dark_url_path;
        }

        return  false;
    }

    public static function hasImageDarkUrl($path) {
        return self::getImageDarkUrl($path) ? true : false;
    }

    public static function getImageUrl($path, $file = "") {
        if ( !empty($file) ) {
            $path = ltrim($path, '/');
            $path = rtrim($path, '/');

            $path = $path . '/' . $file;
        }

        return Theme::getMediaUrlPath() . $path;
    }

    public static function hasImageUrl($path) {
        return self::getImageUrl($path) ? true : false;
    }

    public static function getIllustrationUrl($file) {
        $folder = 'illustrations/' . Theme::getOption('layout', 'illustrations/set');
        $folder = ltrim($folder, '/');
        $folder = rtrim($folder, '/');

        $path =  $folder . '/' . $file;

        return self::getImageUrl($path);
    }

    public static function getIllustrationDarkUrl($file) {
        $folder = 'illustrations/' . Theme::getOption('layout', 'illustrations/set');
        $folder = ltrim($folder, '/');
        $folder = rtrim($folder, '/');

        $path = $folder . '/' . $file;

        $path = str_replace(".svg", "-dark.svg", $path);
        $path = str_replace(".png", "-dark.png", $path);
        $path = str_replace(".jpg", "-dark.jpg", $path);

        $path_dark_path = Theme::getMediaPath() . $path;
        $path_dark_url_path = Theme::getMediaUrlPath() .  $path;

        if (file_exists($path_dark_path)) {
            return $path_dark_url_path;
        }

        return  false;
    }

    public static function hasIllustrationUrl($path) {
        return self::getIllustrationUrl($path) ? true : false;
    }

    public static function pagePathStartsWith($value) {
        return substr(Theme::getPagePath(), 0, strlen($value)) === $value;
    }

    public static function getPresetCssFileName($path) {
        $new_path = "";

        if ( self::getOption("layout", "app/general/theme-preset") !== '' && self::getOption("layout", "app/general/theme-preset") !== "default" ) {
            $preset = self::getOption("layout", "app/general/theme-preset");

            if ( strpos($path, "plugins.bundle.css") !== false ) {
                $new_path = str_replace("plugins.bundle.css", "plugins." . $preset . ".bundle.css", $path);
            } else if ( strpos($path, "style.bundle.css") !== false ) {
                $new_path = str_replace("style.bundle.css", "style." . $preset . ".bundle.css", $path);
            }
        }

        if ( !empty($new_path) && file_exists( Theme::getAssetsPath() . $new_path ) === true ) {
            return $new_path;
        } else {
            return $path;
        }
    }

    public static function getSvgIcon($path, $class = '', $svgClass = '')
    {
        // for generating framrwork specific export
        $framework = $_REQUEST['framework'] ?? 'html';

        $path = str_replace('\\', '/', trim($path));

        $full_path = $path;

        if (!file_exists($path)) {
            $full_path = self::getMediaPath().$path;

            if (!is_string($full_path)) {
                return '';
            }

            if (!file_exists($full_path)) {
                return "<!--SVG file not found: $path-->\n";
            }
        }

        $cls = array('svg-icon');

        if (!empty($class)) {
            $cls = array_merge($cls, explode(' ', $class));
        }

        if (!empty($framework) && $framework !== "html") {
            return self::getFrameworkSvgIconIncludeCode($framework, $path, implode(' ', $cls));
        }

        $svg_content = file_get_contents($full_path);

        if ( !empty($svgClass) ) {
            $svg_content = str_replace("<svg ", "<svg class=\" . $svgClass .  \"", $svg_content);
        }

        $output = "<!--begin::Svg Icon | path: $path-->\n";
        $output .= '<span class="'.implode(' ', $cls).'">'.$svg_content.'</span>';
        $output .= "\n<!--end::Svg Icon-->";

        return $output;
    }

    public static function getFrameworkSvgIconIncludeCode($framework, $path, $class = '')
    {
        $content = '';

        if ($framework === 'django') {
            $content = "{% getSvgIcon 'assets/media/$path' '$class' %}";
        }

        if ($framework === 'flask') {
            $content = "{{ getSvgIcon('assets/media/$path', '$class') }}";
        }

        if ($framework === 'asp.net-core') {
            $content = "@Html.Raw(KTTheme.getSvgIcon(\"/assets/media/$path\", \"$class\"))";
        }

        if ($framework === 'blazor') {
            $content = "@((MarkupString)KTTheme.getSvgIcon(\"$path\", \"$class\"))";
        }

        return "\n".$content."\n";
    }

}
