<!DOCTYPE html>
<html lang="en">

<head>
    <base href="<%= basePath %>">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
    <meta name="description" content="txAdmin - remotely Manage & Monitor your GTA5 FiveM Server">
    <meta name="author" content="André Tabarra">
    <title>Server Deployer</title>
    <link href="css/simple-line-icons.css?txVer=<%= txAdminVersion %>" rel="stylesheet">
    <link href="css/coreui.min.css?txVer=<%= txAdminVersion %>" rel="stylesheet">
    <link href="css/dark.css?txVer=<%= txAdminVersion %>" rel="stylesheet">
    <link rel="shortcut icon" type="image/png" href="img/favicon_default.png" id="favicon" />
    <link rel="stylesheet" href="css/txAdmin.css?txVer=<%= txAdminVersion %>">

    <!-- Page CSS -->
    <!-- <link rel="stylesheet" href="css/codemirror.css"> -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.61.1/codemirror.min.css" 
        integrity="sha512-xIf9AdJauwKIVtrVRZ0i4nHP61Ogx9fSRAkCLecmE2dL/U8ioWpDvFCAy4dcfecN72HHB9+7FfQj3aiO68aaaw==" 
        crossorigin="anonymous" referrerpolicy="no-referrer" />
    <link rel="stylesheet" href="css/codemirror_lucario.css?txVer=<%= txAdminVersion %>">
    <style>
        .inline-code{
            color: #321fdb!important;
        }
        body.theme--dark .inline-code {
            color: #00bf8f !important;
        }
        .cm-s-lucario{
            font-size: 1.05rem !important;
        }
        .deployer-stepper > .card-header,
        .deployer-stepper > .card-footer{
            font-size: large;
        }

        #step3Log {
            white-space: break-spaces;
            word-break: break-all;
        }
    </style>
    
    <!-- injected consts -->
    <script><%- jsInjection %></script>
</head>

<body class="c-app flex-row <%= uiTheme %>">
    <div class="container">

        <!-- Stepper Row -->
        <div class="row justify-content-center">
            <div class="col-12">
                <div class="card fade-in deployer-stepper">
                    <% if (step === 'review') { %>
                        <style>
                            .CodeMirror{
                                max-height: 300px;
                            }
                        </style>
                        <div class="card-header font-weight-bold">Step 1: Review Recipe</div>
                        <div class="card-body">
                            <div class="row mb-1 mt-0 text-center">
                                <div class="col-8 mx-auto card d-block border-primary p-2 mb-1">
                                    Please review the Recipe below and apply any changes you want, <br>
                                    then press the <strong>Run Recipe</strong> button below.
        
                                    <% if (!recipe.isTrustedSource) { %>
                                        <br><span class="text-danger font-weight-bold">Warning: Only run Recipes from trusted sources!</span>
                                    <% } %>
                                </div>
                            </div>
                            <p class="mb-1">
                                <strong style="word-wrap: break-word;"><%= recipe.name %></strong>
                                <% if (recipe.author !== '') { %>
                                    by <%= recipe.author %>
                                <% } %>
                                <% if (recipe.description !== '') { %>
                                    <br>
                                    <%= recipe.description %>
                                <% } %>
                            </p>
                            <textarea 
                                id="codeMirrorTarget"
                                style="width: 100%;"
                                class="cms-s-lucario"
                                name="code"
                            >
                                <%= recipe.raw %>
                            </textarea>
                            <div class="row justify-content-center m-2">
                                <button class="btn btn-outline-danger" type="button" 
                                    onclick="cancelAction()">Cancel and Return to Setup</button>
                                &nbsp; &nbsp;
                                <button class="btn btn-info" type="button" 
                                    onclick="step1Action();" autofocus>Next</button>
                            </div>
                        </div>
                        <div class="card-footer text-muted">Step 2: Input Parameters</div>
                        <div class="card-footer text-muted">Step 3: Run Recipe</div>
                        <div class="card-footer text-muted">Step 4: Configure server.cfg</div>
        
                    <% } else if (step === 'input') { %>
                        <div class="card-header">Step 1: Review Recipe ✔️</div>
                        <div class="card-header font-weight-bold ">Step 2: Input Parameters</div>
                        <div class="card-body">
                            <% if (defaults.autofilled) { %>
                                <div class="row mb-3 mt-0 text-center">
                                    <div class="col-8 mx-auto card d-block border-warning p-2 mb-1">
                                        <strong>Note:</strong> The following config was autofilled by <strong>ZAP-Hosting</strong>. <br>
                                        You <i>may</i> edit those, but it's strongly disencouraged.
                                    </div>
                                </div>
                            <% } %>
                            <form id="step2-form">
                                <div class="form-group row">
                                    <label for="step2-svLicense" class="col-sm-3 col-form-label">
                                        License Key
                                        <span class="text-danger">*</span>
                                    </label>
                                    <div class="col-sm-9">
                                        <input type="text" class="form-control blur-input" id="step2-svLicense" maxlength="86" 
                                            autocomplete="off" placeholder="cfxk_xxxxxxxxxxxxxxxxxxxx_xxxxx" 
                                            value="<%= defaults.license %>" required autofocus>
                                        <span class="form-text text-muted">
                                            The license key for your server can be obtained in <a href="https://keymaster.fivem.net/" target="_blank" rel="noopener noreferrer">Keymaster</a>.
                                        </span>
                                    </div>
                                </div>
                                <% if (requireDBConfig) { %>
                                <div class="row justify-content-center m-2">
                                    <a class="btn btn-small btn-outline-secondary" data-toggle="collapse" href="#collapseDbOptions" aria-expanded="true"  aria-controls="collapseDbOptions">
                                        Show/Hide Database options (advanced)
                                    </a>
                                </div>
                                <div class="collapse" id="collapseDbOptions">
                                    <div class="form-group row">
                                        <label for="step2-dbHost" class="col-sm-3 col-form-label">
                                            Database Host
                                            <span class="text-danger">*</span>
                                        </label>
                                        <div class="col-sm-9">
                                            <input type="text" class="form-control" id="step2-dbHost"
                                                placeholder="<%= defaults.mysqlHost %>" value="<%= defaults.mysqlHost %>" required>
                                            <span class="form-text text-muted">
                                                The IP/Hostname for the database server (usually <code><%= defaults.mysqlHost %></code>).
                                            </span>
                                        </div>
                                    </div>
                                    <div class="form-group row">
                                        <label for="step2-dbPort" class="col-sm-3 col-form-label">
                                            Database Port
                                            <span class="text-danger">*</span>
                                        </label>
                                        <div class="col-sm-9">
                                            <input type="number" class="form-control" id="step2-dbPort"
                                                placeholder="<%= defaults.mysqlPort %>" value="<%= defaults.mysqlPort %>" required>
                                            <span class="form-text text-muted">
                                                The port for the database server (usually <code><%= defaults.mysqlPort %></code>).
                                            </span>
                                        </div>
                                    </div>
                                    <div class="form-group row">
                                        <label for="step2-dbUsername" class="col-sm-3 col-form-label">
                                            Database Username
                                            <span class="text-danger">*</span>
                                        </label>
                                        <div class="col-sm-9">
                                            <input type="text" class="form-control" id="step2-dbUsername"
                                                placeholder="<%= defaults.mysqlUser %>" value="<%= defaults.mysqlUser %>" required>
                                            <span class="form-text text-muted">
                                                The database username (usually <code>root</code>).
                                            </span>
                                        </div>
                                    </div>
                                    <div class="form-group row">
                                        <label for="step2-dbPassword" class="col-sm-3 col-form-label">
                                            Database Password
                                        </label>
                                        <div class="col-sm-9">
                                            <input type="text" class="form-control blur-input" id="step2-dbPassword"
                                                autocomplete="off" placeholder="leave it blank" value="<%= defaults.mysqlPassword %>">
                                            <span class="form-text text-muted">
                                                The database password (usually blank).
                                            </span>
                                        </div>
                                    </div>
                                    <div class="form-group row">
                                        <label for="step2-dbName" class="col-sm-3 col-form-label">
                                            Database Name
                                        </label>
                                        <div class="col-sm-9">
                                            <input type="text" class="form-control" id="step2-dbName"
                                                placeholder="<%= defaults.mysqlDatabase %>" value="<%= defaults.mysqlDatabase %>">
                                            <span class="form-text text-muted">
                                                The name of the database to be used or created. <br>
                                                If left empty, the deployment ID (<code><%= deploymentID %></code>) will be used instead.
                                            </span>
                                        </div>
                                    </div>
                                    <div class="form-group row">
                                        <label for="step2-dbDelete" class="col-sm-3 col-form-label">
                                            Delete Database
                                        </label>
                                        <div class="col-sm-9">
                                            <label class="c-switch c-switch-label c-switch-pill c-switch-success fix-pill-form">
                                                <input class="c-switch-input" type="checkbox" id="step2-dbDelete" checked>
                                                <span class="c-switch-slider" data-checked="On" data-unchecked="Off"></span>
                                            </label>
                                            <span class="form-text text-muted">
                                                If already exists, automatically deletes the database with the name provided above. <br>
                                                <strong>Warning:</strong> all data will be lost.
                                            </span>
                                        </div>
                                    </div>
                                </div>
                                <% } %>
                                <% if (inputVars.length) { %>
                                    <div class="hrsep hrsep-small mb-3">Custom Variables</div>
                                    <% for (const [key, inputVar] of inputVars.entries()) { %>
                                        <div class="form-group row">
                                            <label for="step2-customVar<%= key %>" class="col-sm-3 col-form-label">
                                                <%= inputVar.name %>
                                            </label>
                                            <div class="col-sm-9">
                                                <input type="text" class="form-control customRecipeVars" id="step2-customVar<%= key %>" 
                                                    data-varName="<%= inputVar.name %>" placeholder="<%= inputVar.value %>" value="<%= inputVar.value %>">
                                            </div>
                                        </div>
                                    <% } %>
                                <% } %>
                            </form>
                            <div class="row justify-content-center m-2 mt-3">
                                <button class="btn btn-outline-danger" type="button" 
                                    onclick="cancelAction()">Cancel and Return to Setup</button>
                                &nbsp; &nbsp;
                                <button class="btn btn-success" type="button" 
                                    onclick="step2Action();">Run Recipe</button>
                            </div>
                        </div>
                        <div class="card-footer text-muted">Step 3: Run Recipe</div>
                        <div class="card-footer text-muted">Step 4: Configure server.cfg</div>

                    <% } else if (step === 'run') { %>
                        <div class="card-header">Step 1: Review Recipe ✔️</div>
                        <div class="card-header">Step 2: Input Parameters ✔️</div>
                        <div class="card-header font-weight-bold ">Step 3: Run Recipe</div>
                        <div class="card-body">
                            <div class="row mb-1 mt-0 text-center">
                                <div class="col-8 mx-auto card d-block border-primary p-2 mb-1">
                                    Your recipe is being executed, the server will be deployed to: <br>
                                    <code class="inline-code"><%= deployPath %></code>
                                </div>
                            </div>
                            <div class="row mb-3">
                                <div class="col-10 mx-auto card d-block p-2 m-0">
                                    <pre id="step3Log" class="text-body"><h3 class="text-center">🐌🐌🐌</h3></pre>
                                </div>
                            </div>
                            <div class="mx-auto col-8">
                                <div class="progress">
                                    <div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" 
                                        aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" 
                                        style="width: 0%" id="step3Progress">0%</div>
                                </div>
                                <span class="text-danger font-weight-bold d-none" id="step3Error"></span>
                            </div>
                            <div class="row justify-content-center m-2">
                                <button class="btn btn-outline-danger d-none" type="button" 
                                    onclick="cancelAction();" id="step3CancelButton">Cancel and Return to Setup</button>
                                <button type="button" class="btn btn-info d-none"
                                    onclick="window.location.reload();" id="step3NextButton">Next</button>
                            </div>
                        </div>
                        <div class="card-footer text-muted">Step 3: Configure server.cfg</div>
        
                    <% } else if (step === 'configure') { %>
                        <style>
                            .CodeMirror{
                                height: auto;
                            }
                        </style>
                        <div class="card-header">Step 1: Review Recipe ✔️</div>
                        <div class="card-header">Step 2: Input Parameters ✔️</div>
                        <div class="card-header">Step 3: Run Recipe ✔️</div>
                        <div class="card-header font-weight-bold">Step 4: Configure server.cfg</div>
                        <div class="card-body">
                            <div class="row mb-1 mt-0 text-center">
                                <div class="col-8 mx-auto card d-block border-primary p-2 mb-1">
                                    Configure your <code class="inline-code">server.cfg</code> file to your liking, <br>
                                    then press the <strong>Save & Run Server</strong> button below.
                                </div>
                            </div>
        
                            <textarea id="codeMirrorTarget" style="width: 100%;" class="cms-s-lucario" name="code"><%= serverCFG %></textarea>
                            <div class="row justify-content-center m-2">
                                <button class="btn btn-outline-danger" type="button" onclick="cancelAction()">Cancel and Return to Setup</button>
                                &nbsp; &nbsp;
                                <button class="btn btn-success" type="button" onclick="step4Action();">Save & Run Server</button>
                            </div>
                        </div>
        
                    <% } else { %>
                        <div class="card-body text-center">
                            Something is wrong 🤔
                        </div>
                    <% } %>
                </div>
            </div>
        </div>

    </div>
    <!-- CoreUI and necessary plugins-->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" 
        integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" 
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdn.jsdelivr.net/npm/marked@4.0.16/lib/marked.umd.min.js"></script>
    <script src="js/coreui.bundle.min.js?txVer=<%= txAdminVersion %>"></script>
    <script src="js/bootstrap-notify.min.js?txVer=<%= txAdminVersion %>"></script>
    <script src="js/txadmin/base.js?txVer=<%= txAdminVersion %>"></script>

    <!-- JS -->
    <!-- <script src="js/codeEditor/codemirror.js?txVer=<%= txAdminVersion %>"></script> -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.61.1/codemirror.min.js" 
        integrity="sha512-ZTpbCvmiv7Zt4rK0ltotRJVRaSBKFQHQTrwfs6DoYlBYzO1MA6Oz2WguC+LkV8pGiHraYLEpo7Paa+hoVbCfKw==" 
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="js/codeEditor/mode/simple.js?txVer=<%= txAdminVersion %>"></script>
    <script src="js/codeEditor/mode/fivem-cfg.js?txVer=<%= txAdminVersion %>"></script>
    <script src="js/codeEditor/mode/yaml.js?txVer=<%= txAdminVersion %>"></script>
    <script>
        //============================================== CodeMirror & Page Setup
        const currentStep = '<%= step %>';
        const codeMirrorTarget = document.getElementById("codeMirrorTarget");

        window.onload = function () {
            if(currentStep == 'review' || currentStep == 'configure'){
                window.CMInstance = CodeMirror.fromTextArea(codeMirrorTarget, {
                    mode: (currentStep == 'review')? 'yaml' : 'fivem-cfg',
                    lineNumbers: true,
                    lineWrapping: true,
                    viewportMargin: Infinity,
                    theme: "lucario" //NOTE: I modified the theme a bit
                });
            }
        };


        //============================================== Step1 action
        function step1Action(){
            const editor = window.CMInstance;
            if(editor.getValue().includes('This is just a placeholder')){
                return $.notify({ message: `If you are not trying to write a recipe, click on the cancel button below to return to the setup page, where you can select a recommended template. Otherwise, jut remove the placeholder warning comment.` }, { type: 'warning' });
            }
            editor.setValue(editor.getValue().replace(/\t/g, ' '.repeat(4)));
            const recipe = editor.getValue();
            if(recipe.length < 256){
                return $.notify({ message: `Your Recipe file is too small, there is a good chance you deleted something you shouldn't.` }, { type: 'warning' });
            }
            const notify = $.notify({ message: '<p class="text-center">Saving...</p>' }, {});

            txAdminAPI({
                type: "POST",
                url: '/deployer/recipe/confirmRecipe',
                timeout: REQ_TIMEOUT_LONG,
                data: {recipe},
                success: function (data) {
                    if (checkApiLogoutRefresh(data)) return;
                    if (data.success == true){
                        window.location.reload(true);
                    }else{
                        notify.update('progress', 0);
                        notify.update('type', data.type);
                        notify.update('message', data.message);
                    }
                    
                },
                error: function (xmlhttprequest, textstatus, message) {
                    notify.update('progress', 0);
                    notify.update('type', 'danger');
                    notify.update('message', message);
                }
            });
        }

        //============================================== Step2 action
        const requireDBConfig = ('<%= requireDBConfig %>' == 'true');
        const step2elements = {
            form: document.getElementById('step2-form'),
            svLicense: document.getElementById('step2-svLicense'),
        }
        if(requireDBConfig){
            step2elements.dbHost = document.getElementById('step2-dbHost');
            step2elements.dbPort = document.getElementById('step2-dbPort');
            step2elements.dbUsername = document.getElementById('step2-dbUsername');
            step2elements.dbPassword = document.getElementById('step2-dbPassword');
            step2elements.dbName = document.getElementById('step2-dbName');
            step2elements.dbDelete = document.getElementById('step2-dbDelete');

            step2elements.dbName.addEventListener("keyup", () => {
                const dbName = step2elements.dbName.value.trim()
                step2elements.dbDelete.checked = (dbName == step2elements.dbName.placeholder || !dbName.length);
            });
        }
        
        if(step2elements.form){
            step2elements.form.addEventListener('submit', (e) => {
                e.preventDefault();
                step2Action();
            });
        }

        function step2Action(){
            if(!step2elements.form.reportValidity()) return;
            const postData = {
                svLicense: step2elements.svLicense.value.trim()
            }
            if(requireDBConfig){
                postData.dbHost = step2elements.dbHost.value.trim();
                postData.dbPort = step2elements.dbPort.value.trim();
                postData.dbUsername = step2elements.dbUsername.value.trim();
                postData.dbPassword = step2elements.dbPassword.value.trim();
                postData.dbName = step2elements.dbName.value.trim();
                postData.dbDelete = step2elements.dbDelete.checked;

                if(!postData.dbName.length){
                    postData.dbName = step2elements.dbName.placeholder;
                }
                if(!postData.dbHost || !postData.dbPort || !postData.dbUsername){
                    return $.notify({ message: `The database host, port and username are required.` }, { type: 'warning' });
                }
            }

            //Getting custom forms:
            const customVarInputs = step2elements.form.getElementsByClassName("customRecipeVars");
            for(const input of customVarInputs){
                if(!input.dataset.varname) continue;
                postData[input.dataset.varname] = input.value.trim();
            }

            const notify = $.notify({ message: '<p class="text-center">Saving...</p>' }, {});
            txAdminAPI({
                type: "POST",
                url: '/deployer/recipe/setVariables',
                timeout: REQ_TIMEOUT_LONG,
                data: postData,
                success: function (data) {
                    if (checkApiLogoutRefresh(data)) return;
                    if (data.success == true){
                        window.location.reload(true);
                    }else{
                        notify.update('progress', 0);
                        notify.update('type', data.type);
                        notify.update('message', data.message);
                    }
                    
                },
                error: function (xmlhttprequest, textstatus, message) {
                    notify.update('progress', 0);
                    notify.update('type', 'danger');
                    notify.update('message', message);
                }
            });
        }

        //============================================== Step3 action
        const step3elements = {
            log: document.getElementById('step3Log'),
            progress: document.getElementById('step3Progress'),
            error: document.getElementById('step3Error'),
            cancelButton: document.getElementById('step3CancelButton'),
            nextButton: document.getElementById('step3NextButton'),
        }
        const refreshStatus = async () => {
            txAdminAPI({
                type: "GET",
                url: '/deployer/status',
                timeout: REQ_TIMEOUT_LONG,
                success: function (data) {
                    if (checkApiLogoutRefresh(data)) return;
                    step3elements.error.classList.add('d-none');
                    step3elements.log.innerText = data.log;
                    
                    if(data.status == 'done'){
                        step3elements.progress.classList.remove('progress-bar-animated', 'progress-bar-striped');
                        step3elements.progress.classList.add('bg-success');
                        step3elements.nextButton.classList.remove('d-none');
                        step3elements.progress.ariaValueNow = 100;
                        step3elements.progress.style.width = '100%';
                        step3elements.progress.innerText = 'DONE';
                        
                    }else if(data.status == 'failed'){
                        step3elements.progress.classList.remove('progress-bar-animated', 'progress-bar-striped');
                        step3elements.progress.classList.add('bg-danger');
                        step3elements.cancelButton.classList.remove('d-none');
                        step3elements.progress.ariaValueNow = 100;
                        step3elements.progress.style.width = '100%';
                        step3elements.progress.innerText = 'FAILED';

                    }else{
                        const ariaMin = (data.progress > 5)? data.progress : 5;
                        step3elements.progress.ariaValueNow = ariaMin;
                        step3elements.progress.style.width = ariaMin + '%';
                        step3elements.progress.innerText = data.progress + '%';
                        step3elements.progress.scrollIntoView();

                    }
                },
                error: function (xmlhttprequest, textstatus, message) {
                    step3elements.error.innerText = `Error: ${textstatus}`;
                    step3elements.error.classList.remove('d-none');
                }
            });
        }

        if(currentStep == 'run') setInterval(refreshStatus, 1000);


        //============================================== Step4 action
        function step4Action(){
            const serverCFG = window.CMInstance.getValue();
            if(serverCFG.length < 256){
                return $.notify({ message: `Your settings.cfg file is too small, there is a good chance it is not valid.` }, { type: 'warning' });
            }
            const notify = $.notify({ message: '<p class="text-center">Saving...</p>' }, {});

            if(serverCFG.includes(`sv_licenseKey "changeme"`)){
                return $.notify({ message: `Please change the <strong>sv_licenseKey</strong>.` }, { type: 'danger' });
            }

            txAdminAPI({
                type: "POST",
                url: '/deployer/recipe/commit',
                timeout: REQ_TIMEOUT_LONG,
                data: {serverCFG},
                success: function (data) {
                    if (checkApiLogoutRefresh(data)) return;
                    if (data.success == true){
                        navigateParentTo('/server/console');
                    }else{
                        updateMarkdownNotification(data, notify);
                    }
                },
                error: function (xmlhttprequest, textstatus, message) {
                    notify.update('progress', 0);
                    notify.update('type', 'danger');
                    notify.update('message', message);
                }
            });
        }

        //============================================== cancel action
        function cancelAction(){
            const notify = $.notify({ message: '<p class="text-center">Cancelling...</p>' }, {});
            txAdminAPI({
                type: "POST",
                url: '/deployer/recipe/cancel',
                timeout: REQ_TIMEOUT_LONG,
                success: function (data) {
                    if (checkApiLogoutRefresh(data)) return;
                    if (data.success == true){
                        navigateParentTo('/server/setup');
                    }else{
                        notify.update('progress', 0);
                        notify.update('type', data.type);
                        notify.update('message', data.message);
                    }
                },
                error: function (xmlhttprequest, textstatus, message) {
                    notify.update('progress', 0);
                    notify.update('type', 'danger');
                    notify.update('message', message);
                }
            });
        }
    </script>

</body>

</html>
