<?php

    // Время истечения cookie входа
    $expire_days = 365;
    $delta = $expire_days * 24 * 60 * 60;
    // Продлевать если истекают через
    $expire_less = 180;

    // Продление куки входа
    if ( is_admin() ) {
        $sess = $_COOKIE["sess"];
        $old_expire = (int) $cms["config"]["logged"][$sess]["expire"];
        $pre_expire = $old_expire - $expire_less * 24 * 60 * 60;
        $now = time();
        if ( $now > $pre_expire ) {
            cms_set_cookie( "sess", $sess, $delta );
            // Так же запомнить в конфиге
            $cms["config"]["logged"][$sess]["expire"] = time() + $delta;
            cms_save_config();
        }
    }

    // Для работы выпадающего списка
    if ( empty( $cms["config"]["locale"] ) ) {
        $cms["config"]["locale"] = "en_US.UTF-8";
        $cms["config"]["lang"]   = "en";
    }
    if ( ! empty( $_GET["locale"] ) ) {
        $cms["config"]["locale"] = $_GET["locale"];
        $cms["config"]["lang"]   = substr( $_GET["locale"], 0, 2 );
    }
    
    // Login
    if ( isset( $_POST["login"] ) && isset( $_POST["password"] ) ) {

        // Install process
        if ( empty( $cms["config"]["admin.mod.php"]["admin_login"] )
        && empty( $cms["config"]["admin.mod.php"]["admin_password"] )
        && ( ! empty( $_POST["login"] ) || ! empty( $_POST["password"] ) ) ) {
            $cms["config"]["admin.mod.php"]["admin_login"]    = $_POST["login"];
            $cms["config"]["admin.mod.php"]["admin_password"] = $_POST["password"];
            $cms["config"]["admin.mod.php"]["admin_salt"]     = cms_uid();
            $cms["config"]["admin.mod.php"]["admin_url"]      = "-admin";
            $link = "{$cms['url']['scheme']}://{$cms['url']['host']}{$cms['url']['port']}{$cms['base_path']}{$cms['config']['admin.mod.php']['admin_url']}";
            
            // Set Locale and Timezone
            $cms["config"]["locale"] = $_POST["locale"];
            $cms["config"]["lang"]   = substr( $cms["config"]["locale"], 0, 2 );
            cms_save_config();

            if ( is_email( $cms["config"]["admin.mod.php"]["admin_login"] ) ) {
                $subject = __( "install_finished" );
                $body  = __( "congrat" ) . "\n\n";
                $body .= __( "install_finished" ) . "\n\n";
                $body .= __( "login_info" ) . "\n\n";
                $body .= __( "login_url" ) . ": {$link}\n\n";
                $body .= __( "login" ) . ": {$_POST['login']}\n\n";
                $body .= __( "password" ) . ": {$_POST['password']}";
                cms_email( array(
                    "type" => "text/plain",
                    "from_email" => "noreply@" . $cms["url"]["host"],
                    "from_name"  => $cms["url"]["host"],
                    "to_email"   => $_POST["login"],
                    "subject"    => $subject,
                    "email_body" => $body,
                ) );
            }
        }
        // Check login and password
        if ( $_POST["login"] === $cms["config"]["admin.mod.php"]["admin_login"]
        && $_POST["password"] === $cms["config"]["admin.mod.php"]["admin_password"] ) {
            $d    = date( "Y-m-d H:i:s" );
            $sess = hash(
                "sha256", 
                $cms["config"]["admin.mod.php"]["admin_login"]
                . $cms["config"]["admin.mod.php"]["admin_salt"]
                . $d
            );
            
            // Prepend New Session
            if ( ! isset( $cms["config"]["logged"] ) ) {
                $cms["config"]["logged"] = array();
            }
            
            $cms["config"]["logged"][$sess] = array(
                "ip"         => $_SERVER["REMOTE_ADDR"],
                "date"       => $d,
                "user_agent" => $_SERVER["HTTP_USER_AGENT"],
                "expire"     => time() + $delta,
            );

            // Set Locale and Timezone
            $cms["config"]["locale"] = $_POST["locale"];
            $cms["config"]["lang"]   = substr( $cms["config"]["locale"], 0, 2 );

            if ( cms_save_config() ) {
                cms_set_cookie( "sess", $sess, $delta );
                
                $cms["status"] = "302";
                $cms["status_302_location"] = $cms["base_path"] . $cms["config"]["admin.mod.php"]["admin_url"];
                return;
            } else {
                $error_message = __( "cant_write_config" ) . " .cms/config.php";
            }
        } else {
            $error_message = __( "access_denied" );
        }
    }

    // Тема
    $styles = array(
        "dark modern",
        "light modern",
        "dark classic",
    );
    if ( isset( $_COOKIE["theme"] ) ) {
        $html_classes = $styles[ $_COOKIE["theme"] ];
    } else {
        $html_classes = "dark modern";
    }

    // Инициализация шрифтов
    if ( ! isset( $_COOKIE["fonts"] ) ) {
        if ( preg_match( "/Windows/", $_SERVER["HTTP_USER_AGENT"] ) ) {
            $fonts = "Segoe UI:16px,Consolas:16px";
        } elseif ( preg_match( "/Android/", $_SERVER["HTTP_USER_AGENT"] ) ) {
            $fonts = "Roboto:16px,Droid Sans Mono:16px";
        } else {
            $fonts = "Nunito:16px,Hack:15px";
            // Hack:15px используется так же в input, так что согласовывать с Nunito в других input
        }

        cms_set_cookie( "fonts", $fonts, $delta * 10 );
    } else {
        $fonts = $_COOKIE["fonts"];
    }
    $font = explode( ",", $fonts );
    $font[0] = explode( ":", $font[0] );
    $font[1] = explode( ":", $font[1] );

    // Подключение прилагаемых, если выбраны
    $font_connect = "";
    $font_css = "{$cms['cms_dir']}/fonts/{$font[0][0]}.css";
    if ( is_file( $font_css ) ) {
        $font_connect .= file_get_contents( $font_css );
    }
    $font_mono_css = "{$cms['cms_dir']}/fonts/{$font[1][0]}.css";
    if ( is_file( $font_mono_css ) ) {
        $font_connect .= file_get_contents( $font_mono_css );
    }
    // Если CMS установлена в подпапку, то поправить пути.
    // Или если адрес админки указан как adm/123, то слеш тоже внесет сумятицу,
    // если не использовать абсолютные пути.
    $font_connect = str_replace( "{/}", $cms["base_path"], $font_connect );

?>
<!doctype html>
<html lang="<?php echo $cms["config"]["lang"]; ?>" class="<?php echo $html_classes; ?>">
    <head>
        <style>
            /* Предотвратить белую вспышку */
            html {
                background-color: #000;
                scrollbar-width: none;
            }
        </style>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content">
        <title><?php echo $cms['url']['host']; ?></title>
        <link rel="icon" href="<?php echo $cms["base_path"]; ?>img/favicon.svg">
        <style>
            /* Черный экран вместо дрыгания элементов */
            body {
                opacity: 0;
            }
            body.ready {
                opacity: 1;
            }
            :root {
                --sans-serif: "<?php echo $font[0][0]; ?>", sans-serif;
                --sans-serif-size: <?php echo $font[0][1]; ?>;
                --monospace:  "<?php echo $font[1][0]; ?>", monospace;
                --monospace-size: <?php echo $font[1][1]; ?>;
            }
<?php echo lines_indent( $font_connect, 12 ) . "\n"; ?>
        </style>
        <script>
            // Выполнит callback сразу, если страница уже загружена или дождётся события load
            function onPageReady( callback ) {
                if ( document.readyState === "complete" ) {
                    callback();
                } else {
                    window.addEventListener( "load", callback );
                }
            }

            // Черный экран вместо дергания элементов
            onPageReady( function() {
                // Отображаем
                document.body.classList.add( "ready" );
                
                // Отправляем событие для других скриптов
                // Используем { bubbles: true } чтобы событие всплывало по дереву
                document.body.dispatchEvent( new Event( "ready", { bubbles: true } ) );
            } );
        </script>
<?php
        echo "        <script>
            admin_styles = " . json_pretty( $styles, 12 ) . ";\n";

        if ( is_admin() && ! empty( $cms["config"]["locale"] ) ) {
            $lang = json_pretty( $cms["lang"], 12 ); // Переводы
            $tr   = json_pretty( $cms["tr"], 12 ); // Транслитерация
            $modules = json_pretty( $cms["modules"], 12 );
            if ( is_admin() ) {
                echo "
            cms = {};
            cms.base_path = '{$cms["base_path"]}';
            cms.async_api = true;
            cms.api = '{$cms["base_path"]}{$cms["config"]["admin.mod.php"]["api_url"]}';
            cms.locale = '{$cms["config"]["locale"]}';
            cms.modules = {$modules};
            cms.lang = {$lang};
            cms.tr = {$tr};";
            }
        }
        echo "\n        </script>\n";


        $t = "        ";
        echo "{$t}<script src='{$cms["base_path"]}js/login.js'></script>\n";
        if ( is_admin() ) {
            echo "{$t}<script src='{$cms["base_path"]}js/admin_fn.js'></script>\n";
            echo "{$t}<script src='{$cms["base_path"]}js/admin.js'></script>\n";
        }

        echo "{$t}<link rel=stylesheet href='{$cms["base_path"]}css/admin.css'>\n";
        // Стили и скрипты модулей
        do_hook( "admin_header" );
        ?>

    </head>


<?php if ( is_admin() ) : ?>

    <body class=logged>

        <div class="log">
            <div class="hist"></div>
            <div class="footer">
                <div class="button trash icon">
                    <span></span>
                </div>
                <input type="text" class="message" name="message">
            </div>
        </div>

        <header>
            <div class=tabs></div>

            <div class=menu>
                <div class="button active preload">
                    <!-- Подгрузить картинки нажатой кнопки -->
                </div>
                <div class="button log">
                    <span>Лог</span>
                </div>
                <a href="<?php echo $cms["base_path"]; ?>" data-front target=_blank>
                    <?php echo __( "home_link" ); ?>
                </a>
                <div class=clear-cache>
                    <?php echo __( "cache_btn" ); ?>
                </div>
                <div class=theme>
                    <?php echo __( "theme_btn" ); ?>
                </div>
                <div class=logout>
                    <?php echo __( "logout_btn" ); ?>
                </div>
            </div>

            <div class=burger>
                <div class=icon>
                    <span class=line-1></span>
                    <span class=line-2></span>
                </div>
            </div>
        </header>

        <aside>
<?php
// Боковое меню, секции и пункты
// Сортировка секций происходит в admin.mod.php
foreach( $cms["admin_sections"] as $section_name => $section ) {
    if ( empty( $section["hide"] ) ) {
        // Не выводим пустые секции
        if ( ! empty( $cms["admin_sections"][$section_name]["items"] ) ) {
            
            echo "            <section sort={$section["sort"]}>";
            echo "
                <div class=title>
                    {$cms['admin_sections'][$section_name]['title']}
                </div>";

            foreach( $cms["admin_sections"][$section_name]["items"] as $item_name => $item ) {
                if ( empty( $item["hide"] ) ) {
                    $title = __( $item["title"], $item["module"] );
                    // for highlite
                    if ( ! empty( $item["classes"] ) ) {
                        $class = "class='{$item['classes']}'";
                    } else {
                        $class = "";
                    }
                    if ( empty( $item["url"] ) ) {
                        echo "<a href=#{$item_name} {$class} sort={$item['sort']}>{$title}</a>";
                    } else {
                        echo "<a href='{$item['url']}' target=_blank {$class} sort={$item['sort']}>{$title}</a>";
                    }
                }
            }
            echo "
            </section>\n";
        }
    }
}
?>
        </aside>

        <main>
<?php
    $hello = __( "hello" );
    if ( cms_base_connect() === false ) {
        $base_ok = "<p>" . __( "hello_set_base" ) . "</p>";
    } else {
        $base_ok = "";
    }
    
    echo "
            <section id=start>
                <div class=panel>
                    <div>{$hello}</div>
                    {$base_ok}
                </div>
            </section>
";

    foreach( $cms["admin_pages"] as $name => $page ) {
        // Это не нужно. Мешает некоторым модулям.
        // $page_indent = lines_indent( $page, 16 );
        echo "
            <section id={$name}>
{$page}
            </section>
";
    }
    
?>
        </main>

    <div class=milk></div>

    <div class=notify>
        <!-- div for messages -->
    </div>

<?php else : ?>

<body class=login>
  
    <header>
        <div class=menu>
            <div class=theme>
                <?php echo __( "theme_btn" ); ?>
            </div>
        </div>
    </header>

    

    <main>
        <div class=center>
            <div class=error>
                <?php
                // Если файл существует, то не перезаписывать его,
                // иначе можно менять языки не заходя в админку
                // Но проверку оставить, могут быть сменены права позже
                if ( is_file( $cms["config_file"] ) ) {
                    if ( ! is_writable( $cms["config_file"] ) ) {
                        echo __( "cant_write_config" ) . " {$cms["config_file"]}";
                    }
                }
                // config.php not writeable
                elseif ( cms_save_config() === false ) {
                    echo __( "cant_write_config" ) . " {$cms["config_file"]}";
                }

                // Error login and password
                if ( isset( $error_message ) ) {
                    echo __( $error_message );
                }
                ?>
            </div>
            
            <?php
                // Scan all locales
                $options = "";
                foreach( glob( $cms["cms_dir"] . "/lang/*.UTF-8/admin.mod.php" ) as $lang_file ) {
                    include( $lang_file );
                    preg_match( "/\/lang\/(\w{5}\.UTF-\d{1,2})\//", $lang_file, $m );
                    $locale = $m[1];

                    // translate
                    $lang = $cms["lang"]["admin.mod.php"][$locale][$locale];

                    $options .= "<div class=option value='{$locale}'>{$lang}</div>";
                }
            ?>
            <div class='lang panel'>
                <div class='langs select widget'>
                    <div class=selected data-lang='<?php echo $cms["config"]["locale"]; ?>'>
                        <div class=value>
                            <?php echo $cms["lang"]["admin.mod.php"][$cms["config"]["locale"]][$cms["config"]["locale"]]; ?>
                        </div>
                        <div class='icon down button'>
                            <span></span>
                        </div>
                    </div>
                    <div class=options>
                        <?php echo $options; ?>
                    </div>
                </div>
            </div>
            <div class=setup>
                <?php
                if ( empty( $cms["config"]["admin.mod.php"]["admin_login"] ) && empty( $cms["config"]["admin.mod.php"]["admin_password"] ) ) {
                    echo __( "set_login_and_password" );
                }
                ?>
            </div>

            <script>
            <?php
            $form = "
            <form class='panel' method=post>
                <div class=login>
                    <input placeholder=\"" . __( "login_or_password" ) . "\" name=login type=text>
                </div>
                " . widget( "password_widget.php", array( "password" => "", "placeholder" => __( "password" ) ) ) . "
                <button class=button>
                    <span>" . __( "login_btn" ) . "</span>
                </button>
                <input type=hidden name=locale value=\"{$cms["config"]["locale"]}\">
            </form>";
            $form = base64_encode( $form );
            ?>
            let f = decodeURIComponent( escape( window.atob( "<?php echo $form; ?>" ) ) );
            document.write( f );

            document.querySelectorAll( "form.panel .login input" ).forEach( function( login ) {
                login.focus();
            } );

            const lang_select = document.querySelector( `.select.widget` );
            select_controls( lang_select, { "mode": "init" } );
            // Смена языка
            lang_select.querySelectorAll( ".option" ).forEach( function( option ) {
                option.addEventListener( "click", function( e ) {
                    const locale = option.getAttribute( "value" );
                    let search = window.location.search.replace( /&*locale=[^&]+/, "" );
                    if ( search == "" ) { 
                        search += "?locale=" + locale;
                    } else if ( search == "?" ) {
                        search += "locale=" + locale;
                    } else {
                        search += "&locale=" + locale;
                    }
                    window.location.search = search;
                } );
            } );

            </script>

            <div></div>
            <div class=support>
                <a target=_blank href='<?php echo __( "support_url" ); ?>'>
                    <?php echo __( "support" ); ?>
                </a>
            </div>
        </div>
    </main>
    
<?php endif; ?>


<?php if ( is_admin() ): ?>
<script>
// Codemirror нужен только админу

// Запускаем после полной загрузки всех ресурсов страницы
document.addEventListener( "DOMContentLoaded", function( event ) {
    // Вставка стилей
    document.body.insertAdjacentHTML( "beforeend", `
    <link rel=stylesheet href='${cms.base_path}lib/codemirror/lib/codemirror.css'>
    <link rel=stylesheet href='${cms.base_path}lib/codemirror/addon/hint/show-hint.css'>
    <link rel=stylesheet href='${cms.base_path}lib/codemirror/addon/dialog/dialog.css'>
    <link rel=stylesheet href='${cms.base_path}lib/codemirror/addon/fold/foldgutter.css'>
    ` );

    // Первый скрипт — ядро, должно загрузиться первым
    const coreScript = "lib/codemirror/lib/codemirror.js";

    // Остальные скрипты — аддоны и режимы, можно грузить параллельно
    const addonScripts = [
        "lib/codemirror/addon/hint/show-hint.js",
        "lib/codemirror/addon/hint/xml-hint.js",
        "lib/codemirror/addon/hint/html-hint.js",
        "lib/codemirror/addon/hint/javascript-hint.js",
        "lib/codemirror/addon/hint/anyword-hint.js",
        "lib/codemirror/addon/hint/css-hint.js",
        "lib/codemirror/addon/selection/active-line.js",
        "lib/codemirror/addon/search/search.js",
        "lib/codemirror/addon/search/searchcursor.js",
        "lib/codemirror/addon/search/jump-to-line.js",
        "lib/codemirror/addon/dialog/dialog.js",
        "lib/codemirror/addon/edit/matchbrackets.js",
        "lib/codemirror/addon/edit/matchtags.js",
        "lib/codemirror/addon/edit/closebrackets.js",
        "lib/codemirror/addon/edit/closetag.js",

        "lib/codemirror/addon/fold/foldcode.js",
        "lib/codemirror/addon/fold/foldgutter.js",
        "lib/codemirror/addon/fold/brace-fold.js",
        "lib/codemirror/addon/fold/xml-fold.js",
        // "lib/codemirror/addon/fold/indent-fold.js",
        // "lib/codemirror/addon/fold/markdown-fold.js",
        "lib/codemirror/addon/fold/comment-fold.js",

        "lib/codemirror/mode/htmlmixed/htmlmixed.js",
        "lib/codemirror/mode/xml/xml.js",
        "lib/codemirror/mode/javascript/javascript.js",
        "lib/codemirror/mode/css/css.js",
        "lib/codemirror/mode/clike/clike.js",
        "lib/codemirror/mode/php/php.js",
    ];
                
    // Функция для загрузки одного скрипта с возвращением Promise
    function loadScript(src) {
        return new Promise((resolve, reject) => {
            const script = document.createElement("script");
            script.src = cms.base_path + src;
            script.async = false; // Важно: отключаем асинхронность
            script.onload = resolve;
            script.onerror = () => reject(new Error(`Failed to load: ${src}`));
            document.body.appendChild(script);
        });
    }

    // 1. Сначала грузим ядро (синхронно, без async)
    loadScript(coreScript, false)
    .then(() => {
        console.log("CodeMirror core loaded. Loading addons...");
        
        // 2. После загрузки ядра — грузим все аддоны параллельно (async)
        const parallelLoads = addonScripts.map(src => 
            loadScript(src, true).catch(err => console.warn(err))
        );
        
        // Ждём завершения всех параллельных загрузок
        return Promise.all(parallelLoads);
    })
    .then(() => {
        console.log("All CodeMirror scripts loaded.");
        // Инициализация редактора, если нужно:
        // if (typeof CodeMirror !== 'undefined') { ... }
    })
    .catch((error) => {
        console.error("Critical error loading CodeMirror core:", error);
    });
} );
</script>
<?php endif; ?>

</body>
</html>
