<!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><%= headerTitle %></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="https://fonts.googleapis.com/icon?family=Material+Icons">
    <link rel="stylesheet" href="https://unpkg.com/materialize-stepper@3.1.0/dist/css/mstepper.min.css">

    <style>
        code:not(.keep-original){
            color: #321fdb!important;
        }
        body.theme--dark code:not(.keep-original) {
            color: #0d86ff !important;
        }
        .bigbutton{
            cursor: pointer;
            background-color: #f7f7f7;
            -webkit-transition: background-color 250ms linear, color 50ms linear;
            -ms-transition: background-color 250ms linear, color 50ms linear;
            transition: background-color 250ms linear, color 50ms linear;
        }
        .bigbutton:hover:not(.disabled){
            background-color: #2196f3 !important;
            color: white; 
        }
        .bigbutton.disabled:hover{
            background-color: #424242 !important;
            color: white; 
        }
        .bigbutton.disabled{
            cursor: not-allowed;
        }
        .bigbutton em{
            -webkit-transition: color 50ms linear;
            -ms-transition: color 50ms linear;
            transition: color 50ms linear;
        }
        .bigbutton:hover:not(.disabled) em{
            color: var(--light)!important;
        }
        .stepper{
            list-style: none;
            padding-inline-start: 20px;
        }
        .deployment-type-card{
            border-radius: 15px;
            margin: 0.75em;
            padding: 0.75rem 1rem;
        }
        .deployment-type-card > .card-body{
            padding: 0.75rem !important;
        }
        .template-cards{
            margin: 5px;
            padding: 8px;
            height: 5.1rem;
            border-radius: 5px;
        }
        .template-cards > span{
            overflow: hidden;
            word-wrap: break-word;
            text-overflow: ellipsis;
            display: -webkit-box;
            -webkit-box-orient: vertical;
        }
        .template-cards > .titleText{
            -webkit-line-clamp: 1;
        }
        .template-cards > .description{
            -webkit-line-clamp: 2;
        }
        .template-cards > .titleText::before{
            content: "⭐";
        }
        .template-cards > .title{
            display: flex;
            flex-direction: row;
            align-items: center;
            justify-content: space-between;
        }
        .template-cards .tagList{
            display: flex;
            flex-direction: row-reverse;
        }

        .recipeTag {
            display: inline-block;
            padding: .25em .4em;
            font-size: 75%;
            font-weight: 700;
            line-height: 1;
            text-align: center;
            white-space: nowrap;
            vertical-align: baseline;
            border-radius: .25rem;
            margin: 0px 0.15rem;
        }
        .recipeTagFivem {
            color: #FF8637;
            border: 1px solid #FF8637;
        }
        .recipeTagRedm {
            color: #FA0211;
            border: 1px solid #FA0211;
        }
        .recipeTagDefault {
            color: #6b6b6b;
            border: 1px solid #6b6b6b;
        }
        body.theme--dark .recipeTagDefault {
            color: #d6d6d6;
            border: 1px solid #d6d6d6;
        }
    </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 col-md-12 col-lg-8">
                <div class="card fade-in">
                    <div class="card-body">
                        <ul class="stepper linear">

                            <!-- Server Name -->
                            <li class="step <%= skipServerName ? 'done' : 'active' %>">
                                <div class="step-title waves-effect">Server Name</div>
                                <div class="step-content">
                                    A <strong>short</strong> server name to be used in txAdmin interface and
                                    Chat/Discord messages.
                                    <input type="text" class="form-control mt-2" id="frmName" maxlength="18"
                                        minlength="1" placeholder="Happy Server" value="<%= serverName %>" required>
                                    <span id="frmNameError" class="text-danger fade-in d-none"></span>
                                    <div class="step-actions">
                                        <button class="btn btn-pill btn-secondary previous-step"
                                            type="button">Back</button>
                                        <button class="btn btn-pill btn-info next-step" type="button"
                                            data-feedback="validateName" id="frmNameSubmitBtn">Next</button>
                                    </div>
                                </div>
                            </li>


                            <!-- Deployment Type -->
                            <li class="step <%= skipServerName ? 'active' : '' %>">
                                <div class="step-title waves-effect">Deployment Type</div>
                                <div class="step-content">
                                    <strong>Select</strong> how you want to setup your server:
                                    <div class="bigbutton deployment-type-card border-dark next-step" onclick="selectDeploymentType('popular')">
                                        <span class="title"><strong>⭐ Popular Recipes</strong> <span class="badge badge-danger">RECOMMENDED</span></span>
                                        <br>
                                        <span class="description">
                                            Select a template from a curated list of community favorites. <br>
                                            This includes QBCore, ESX and a Default template for you to customize.
                                        </span>
                                    </div>
                                    <div class="bigbutton deployment-type-card border-dark next-step" onclick="selectDeploymentType('local')">
                                        <span class="title"><strong>📁 Existing Server Data</strong></span>
                                        <br>
                                        <span class="description">
                                            Select an existing server data folder in the host. <br>
                                            Only select this option if you already have a <code class="keep-original">server.cfg</code> and a <code class="keep-original">resources</code> folder. <br>
                                            If you are not running fxserver in your computer, you need to first upload those files to the server's host.
                                        </span>
                                    </div>
                                    <div class="bigbutton deployment-type-card border-dark next-step" onclick="selectDeploymentType('remote')">
                                        <span class="title"><strong>📥 Remote URL Template</strong></span>
                                        <br>
                                        <span class="description">
                                            Based on a Recipe URL in the YAML format. <br>
                                            You will have the option to edit the Recipe before running it.
                                        </span>
                                    </div>
                                    <div class="bigbutton deployment-type-card border-dark next-step" onclick="selectDeploymentType('custom')">
                                        <span class="title"><strong>📑 Custom Template</strong></span>
                                        <br>
                                        <span class="description">
                                            This is recommended if you have a custom recipe-based server or if you are writing your own recipe. 
                                            You will be asked for the recipe right after this page.
                                        </span>
                                    </div>
                                    <div class="step-actions">
                                        <button class="btn btn-pill btn-secondary previous-step"
                                            type="button">Back</button>
                                    </div>
                                </div>
                            </li>


                            <!-- Step 4 -->
                            <li class="step">
                                <div class="step-title waves-effect" id="s4Title"><i>please select deployment type</i></div>
                                <div class="step-content">
                                    <!-- select template buttons -->
                                    <template id="s4PopularTemplateCardTemplate">
                                        <div class="bigbutton template-cards border-dark next-step">
                                            <div class="title">
                                                <span class="titleText">
                                                    <strong></strong>
                                                </span>
                                                <div class="tagList"></div>
                                            </div>
                                            <span class="description"></span>
                                        </div>
                                    </template>
                                    <div class="d-none" id="s4PopularTemplateDiv">
                                        <div class="row" id="s4PopularTemplateRow"></div> 
                                        
                                        <div class="step-actions">
                                            <button class="btn btn-pill btn-secondary previous-step"
                                                type="button">Back</button>
                                        </div>
                                    </div>

                                    <!-- input url with some minimal backend validation -->
                                    <div class="d-none" id="s4RemoteTemplateDiv">
                                        The URL for the remote recipe, or the forum thread. <br>
                                        You can discover new recipes by visiting the <a href="https://forum.cfx.re/c/development/releases/7" target="_blank" rel="noopener noreferrer">CFX Forum</a>.
                                        <input type="text" class="form-control mt-2" id="s4RemoteTemplateInput"
                                            placeholder="https://raw.githubusercontent.com/tabarra/CFX-Default-recipe/main/recipe.yaml">
                                        <span id="s4RemoteTemplateInputError" class="text-danger fade-in d-none"></span>
                                        <div class="step-actions">
                                            <button class="btn btn-pill btn-secondary previous-step"
                                                type="button">Back</button>
                                            <button class="btn btn-pill btn-info next-step" type="button"
                                                data-feedback="validateRemoteTemplate">Next</button>
                                        </div>
                                    </div>

                                    <!-- explain and show some doc links -->
                                    <div class="d-none" id="s4CustomTemplateDiv">
                                        <p>
                                            In the next page you will be prompted to insert your custom Recipe. <br>
                                            If you are developing your own recipes, we highly recommend you to check the following:
                                            <ul class="font-weight-bold">
                                                <li><a href="https://github.com/tabarra/txAdmin/blob/master/docs/recipe.md" target="_blank" rel="noopener">Recipe Documentation</a></li>
                                                <li><a href="https://github.com/tabarra/txAdmin-recipes" target="_blank" rel="noopener">Example Recipes</a></li>
                                                <li><a href="https://discord.gg/NsXGTszYjK" target="_blank" rel="noopener">Discord Support</a></li>
                                            </ul>
                                        </p>
                                        
                                        <div class="step-actions">
                                            <button class="btn btn-pill btn-secondary previous-step"
                                                type="button">Back</button>
                                            <button class="btn btn-pill btn-info next-step" 
                                                type="button">Next</button>
                                        </div>
                                    </div>

                                    <!-- input local data folder -->
                                    <div class="d-none" id="s4LocalDataPathDiv">
                                        The folder that <strong>contains</strong> the <code>resources</code> and
                                        <code>cache</code> folders, usually it's here that you put your <code>server.cfg</code>. <br>
                                        Also known as Base Folder. <br>
                                        <% if (hasCustomDataPath) { %>
                                            <span class="font-weight-bold"><%= hostConfigSource %>: this path should start with <code><%= dataPath %></code>.</span>
                                        <% } %>
                                        <input type="text" class="form-control mt-2" id="s4LocalDataPathInput"
                                            placeholder="C:/Users/Admin/Desktop/server01">
                                        <span id="s4LocalDataPathInputError" class="text-danger fade-in d-none"></span>
                                        <div class="step-actions">
                                            <button class="btn btn-pill btn-secondary previous-step"
                                                type="button">Back</button>
                                            <button class="btn btn-pill btn-info next-step" type="button"
                                                data-feedback="validateLocalDataFolder" id="s4LocalDataPathInputSubmitBtn">Next</button>
                                            <button class="btn btn-pill btn-outline-primary d-none fade-in" type="button"
                                                id="s4LocalDataPathInputFixBtn" 
                                                data-target="s4LocalDataPathInput">Accept Fix</button>
                                        </div>
                                    </div>

                                </div>
                            </li>


                            <!-- Step 5 -->
                            <li class="step">
                                <div class="step-title waves-effect" id="s5Title"><i>please select deployment type</i></div>
                                <div class="step-content" id="s5Content">

                                    <!-- input local data folder --> 
                                    <div class="d-none" id="s5DeployerTargetDiv">
                                        The folder where the server will be deployed to. <br>
                                        This folder will contain all your resources and configuration files. <br>
                                        <% if (hasCustomDataPath) { %>
                                            <span class="font-weight-bold"><%= hostConfigSource %>: this path must start with <code><%= dataPath %></code>.</span> <br>
                                        <% } %>
                                        <strong>We strongly recommend using the path suggested below.</strong>                     
                                        <div class="input-group mt-2">
                                            <input type="text" class="form-control" id="s5DeployerTargetInput"
                                                placeholder="C:/Users/Admin/Desktop/server01/server.cfg" disabled>
                                            <span class="input-group-append">
                                                <button class="btn btn-sm btn-outline-dark" type="button" id="s5DeployerTargetChangeBtn"
                                                    onclick="s5DeployerTargetEnablePath()">Change Path</button>
                                            </span>
                                        </div>
                                        <span id="s5DeployerTargetError" class="text-danger fade-in d-none"></span>
                                        <div class="step-actions">
                                            <button class="btn btn-pill btn-secondary previous-step"
                                                type="button">Back</button>
                                            <button class="btn btn-pill btn-info next-step" type="button"
                                                data-feedback="validateLocalDeployPath" id="s5DeployerTargetSubmitBtn" autofocus>Save</button>
                                        </div>
                                    </div>

                                    <!-- input server cfg file -->
                                    <div class="d-none" id="s5ServerCFGDiv">
                                        The path to your server config file, usually named <code>server.cfg</code>. <br>
                                        This can either be absolute, or relative to the Server Data folder.
                                        <input type="text" class="form-control mt-2" id="s5ServerCFGInput"
                                            placeholder="C:/Users/Admin/Desktop/server01/server.cfg">
                                        <p class="text-success font-weight-bold mb-0 d-none" id="s5ServerCFGAutofill">
                                            Config file detected! If this file is correct, just click on the save button below.
                                        </p>
                                        <span id="s5ServerCFGError" class="text-danger fade-in d-none"></span>
                                        <div class="step-actions">
                                            <div class="step-actions">
                                                <button class="btn btn-pill btn-secondary previous-step"
                                                    type="button">Back</button>
                                                <button class="btn btn-pill btn-info next-step" type="button"
                                                    data-feedback="validateCFGFile" id="s5ServerCFGSubmitBtn">Save</button>
                                            </div>
                                        </div>
                                    </div>
                                    
                                </div>
                            </li>


                            <!-- Finish -->
                            <li class="step">
                                <div class="step-title waves-effect">Finish</div>
                                <div class="step-content">
                                    <h4 id="finishMessage">We are all set!</h4>
                                    <span id="saveError" class="text-danger fade-in d-none"></span>
                                    <div class="step-actions">
                                        <button class="btn btn-pill btn-success next-step" type="button" 
                                            data-feedback="performSave" id="finishButton">
                                            Save & Start Server</button>
                                    </div>
                                </div>
                            </li>

                        </ul>
                    </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="https://unpkg.com/materialize-stepper@3.1.0/dist/js/mstepper.js"></script>
    <script>
        //Constants
        const recipesIndexURL = 'https://raw.githubusercontent.com/citizenfx/txAdmin-recipes/refs/heads/main/indexv4.json';
        const txDataPath = '<%= dataPath %>';
        const forceGameName = '<%= forceGameName %>' || false;
        const deployerEngineVersion = parseInt('<%= deployerEngineVersion %>');
        const skipServerName = ('<%= skipServerName %>' === 'true');
        const SPINNER_HTMLSized = `<div style="min-height: 250px; margin: auto;">${SPINNER_HTML}</div>`;
        const connectErrorMessage = `<b>Unable to connect to txAdmin.</b> <br> If you closed it, please start again and retry.`;

        //Vars
        const suggestions = {};
        let loadedTemplates = [];
        let selectedTemplateIndex;
        let selectedDeploymentType;
        let deploymentID;

        //Stepper config
        const stepper = document.querySelector('.stepper');
        const stepperInstace = new MStepper(stepper, {
            autoFocusInput: true,
            showFeedbackPreloader: true,
            stepTitleNavigation: false,
            firstActive: skipServerName ? 1 : 0,
            feedbackPreloader: SPINNER_HTMLSized,
        });

        //Functions
        const buildDeployName = (templateName) => {
            const treatedName = templateName.replace(/[^a-zA-Z0-9\.\-_]/g, '');
            const shortName = (treatedName.length < 3)? 'DumbName' : treatedName;
            const timestamp = Math.round(Date.now()/1000).toString(16).padStart(6, 0).slice(-6).toUpperCase();
            return {
                id: `${shortName}_${timestamp}`,
                path: `${txDataPath}/${shortName}_${timestamp}.base`,
            };
        }
        const inputKeyUp = (event) => {
            event.target.classList.remove('is-invalid', 'is-valid');
            if (event.target.id == 's5ServerCFGInput'){
                s5ServerCFGAutofill.classList.add('d-none');
            }
            if (event.keyCode === 13) {
                event.preventDefault();
                document.getElementById(event.target.id+'SubmitBtn').click();
            }
        }
        const acceptFix = (event) => {
            event.target.classList.add('d-none');
            const targetName = event.target.dataset.target;
            const targetElement = document.getElementById(targetName);
            targetElement.classList.remove('is-invalid');
            targetElement.classList.add('is-valid');
            targetElement.value = suggestions[targetName] || '';
            const currentSteps = stepperInstace.getSteps();
            currentSteps.active.step.classList.remove('wrong');
            currentSteps.active.step.classList.add('done');
        }


        //Grabs the elements and set the event handlers
        const finishButton = document.getElementById("finishButton");
        const finishMessage = document.getElementById("finishMessage");
        const frmName = document.getElementById("frmName");
        const frmNameError = document.getElementById("frmNameError");
        frmName.addEventListener("keyup", inputKeyUp);

        //Step 4
        const s4Title = document.getElementById("s4Title");
        const s4PopularTemplateDiv = document.getElementById("s4PopularTemplateDiv");
        const s4PopularTemplateCardTemplate = document.getElementById("s4PopularTemplateCardTemplate");
        const s4PopularTemplateRow = document.getElementById("s4PopularTemplateRow");
        const s4RemoteTemplateDiv = document.getElementById("s4RemoteTemplateDiv");
        const s4CustomTemplateDiv = document.getElementById("s4CustomTemplateDiv");
        const s4LocalDataPathDiv = document.getElementById("s4LocalDataPathDiv");

        const s4RemoteTemplateInput = document.getElementById("s4RemoteTemplateInput");
        const s4RemoteTemplateInputError = document.getElementById("s4RemoteTemplateInputError");
        s4RemoteTemplateInput.addEventListener("keyup", inputKeyUp);

        const s4LocalDataPathInput = document.getElementById("s4LocalDataPathInput");
        const s4LocalDataPathInputError = document.getElementById("s4LocalDataPathInputError");
        const s4LocalDataPathInputFixBtn = document.getElementById("s4LocalDataPathInputFixBtn");
        s4LocalDataPathInput.addEventListener("keyup", inputKeyUp);
        s4LocalDataPathInputFixBtn.addEventListener("click", acceptFix);

        //Step 5
        const s5Title = document.getElementById("s5Title");
        const s5Content = document.getElementById("s5Content");
        const s5DeployerTargetDiv = document.getElementById("s5DeployerTargetDiv");
        const s5ServerCFGDiv = document.getElementById("s5ServerCFGDiv");
        
        const s5DeployerTargetChangeBtn = document.getElementById("s5DeployerTargetChangeBtn");
        const s5DeployerTargetInput = document.getElementById("s5DeployerTargetInput");
        const s5DeployerTargetError = document.getElementById("s5DeployerTargetError");
        s5DeployerTargetInput.addEventListener("keyup", inputKeyUp);

        const s5ServerCFGInput = document.getElementById("s5ServerCFGInput");
        const s5ServerCFGAutofill = document.getElementById("s5ServerCFGAutofill");
        const s5ServerCFGError = document.getElementById("s5ServerCFGError");
        s5ServerCFGInput.addEventListener("keyup", inputKeyUp);
        
        
        // Server Name step validation
        function validateName(destroyFeedback) {
            frmName.classList.remove('is-invalid', 'is-valid');
            frmNameError.classList.add('d-none');
            const name = frmName.value.trim();

            if(name.length < 1 || name.length > 18){
                frmNameError.innerHTML = `The name must have between 1 and 18 characters.`;
                frmNameError.classList.remove('d-none');
                frmName.classList.add('is-invalid');
                stepperInstace.wrongStep();
                destroyFeedback(false)
            }else{
                frmName.classList.add('is-valid');
                destroyFeedback(true)
            }
        }

        // Deployment type selection
        function selectDeploymentType(depType){
            console.log(`Selected ${depType}`);
            selectedDeploymentType = depType;
            selectedTemplateURL = null;
            if(depType == 'popular' || depType == 'remote'){
                s4Title.textContent = "Select Template";
                s5Title.textContent = "Data Location";
                finishButton.textContent = "Go to Recipe Deployer";
                finishMessage.textContent = "We are almost there!";
                s4PopularTemplateRow.innerHTML = SPINNER_HTMLSized;
                s4CustomTemplateDiv.classList.add('d-none');
                s4LocalDataPathDiv.classList.add('d-none');
                s5DeployerTargetDiv.classList.remove('d-none');
                s5ServerCFGDiv.classList.add('d-none');
                
                if(depType == 'popular'){
                    s4PopularTemplateDiv.classList.remove('d-none');
                    s4RemoteTemplateDiv.classList.add('d-none');
                    setFavTemplatesCards();
                }else{
                    s4PopularTemplateDiv.classList.add('d-none');
                    s4RemoteTemplateDiv.classList.remove('d-none');
                }

            }else if(depType == 'custom'){
                const deployData = buildDeployName(frmName.value.trim());
                s5DeployerTargetInput.value = deployData.path;
                deploymentID = deployData.id;

                s4Title.textContent = "Information";
                s5Title.textContent = "Data Location";
                finishButton.textContent = "Go to Recipe Deployer";
                finishMessage.textContent = "We are almost there!";
                s4CustomTemplateDiv.classList.remove('d-none');
                s4RemoteTemplateDiv.classList.add('d-none');
                s4PopularTemplateDiv.classList.add('d-none');
                s4LocalDataPathDiv.classList.add('d-none');
                s5DeployerTargetDiv.classList.remove('d-none');
                s5ServerCFGDiv.classList.add('d-none');
                
            }else if(depType == 'local'){
                s4Title.textContent = "Existing Server Data";
                s5Title.textContent = "Server CFG File";
                finishButton.textContent = "Save & Start Server";
                finishMessage.textContent = "We are all set!";
                s4PopularTemplateDiv.classList.add('d-none');
                s4CustomTemplateDiv.classList.add('d-none');
                s4RemoteTemplateDiv.classList.add('d-none');
                s4LocalDataPathDiv.classList.remove('d-none');
                s5DeployerTargetDiv.classList.add('d-none');
                s5ServerCFGDiv.classList.remove('d-none');
            }else{
                alert('Unknown deployment type!');
                window.location.reload(true);
            }
        }

        function tagToGlass(tag) {
            if (tag === 'fivem') {
                return 'recipeTagFivem';
            } else if (tag === 'redm') {
                return 'recipeTagRedm';
            } else {
                return 'recipeTagDefault';
            }
        }

        //Download Popular Recipe list and create cards
        async function setFavTemplatesCards(){
            //NOTE: mocked
            // const tmpGETResponse = [
            //     {
            //         "engine": 3,
            //         "name": "CFX Default",
            //         "author": "Tabarra",
            //         "version": "3.0.0",
            //         "description": "Recipe for the base resources required to run a minimal FiveM server.",
            //         "url": "https://raw.githubusercontent.com/tabarra/CFX-Default-recipe/main/recipe.yaml"
            //     },
            //     {
            //         "engine": 3,
            //         "name": "Plume ESX",
            //         "author": "Tabarra & Chip",
            //         "version": "2.0.0",
            //         "description": "A full featured (13 jobs) and highly configurable yet lightweight ESX v1-final base that can be easily extendable.",
            //         "url": "https://raw.githubusercontent.com/tabarra/PlumeESX-recipe/master/recipe.yaml"
            //     }
            // ];
            s4PopularTemplateRow.innerText = `Loading templates...`;
            loadedTemplates = [];
            $.ajax({
                type: "GET",
                url: recipesIndexURL,
                dataType: 'json',
                success: function (templates) {
                    if(!Array.isArray(templates)){
                        s4PopularTemplateRow.innerText = `Failed to load recipe list. 
                        Please click on the "back" button and try again.`;
                    }else{
                        loadedTemplates = templates;
                        // loadedTemplates = tmpGETResponse;
                        s4PopularTemplateRow.innerHTML = '';
                        let hasIncompatible = false;
                        loadedTemplates.forEach((recipe, key) => {
                            //Filtering for forceGameName
                            if (
                                forceGameName
                                && Array.isArray(recipe.tags)
                                && !recipe.tags.includes(forceGameName)
                            ) return;

                            const newNode = document.createElement("div");
                            newNode.innerHTML = s4PopularTemplateCardTemplate.innerHTML;
                            // newNode.classList.add('col-12', 'col-md-6', 'p-0'); //2 per line
                            newNode.classList.add('col-8');
                            newNode.querySelector('.titleText > strong').innerText = recipe.name;
                            newNode.querySelector('.description').innerText = recipe.description;
                            if(recipe.engine !== deployerEngineVersion){
                                hasIncompatible = true;
                                newNode.querySelector('.bigbutton').classList.add('disabled');
                                const newTag = document.createElement("span");
                                newTag.classList.add('recipeTag', 'recipeTagDefault')
                                newTag.textContent = 'INCOMPATIBLE';
                                newNode.querySelector('.tagList').appendChild(newTag);
                            }else{
                                newNode.querySelector('.bigbutton').onclick = () => {selectTemplate(key)};
                                if (Array.isArray(recipe.tags)) {
                                    recipe.tags.forEach(tag => {
                                        const newTag = document.createElement("span");
                                        newTag.classList.add('recipeTag', tagToGlass(tag))
                                        newTag.textContent = (tag || '').toUpperCase();
                                        newNode.querySelector('.tagList').appendChild(newTag);
                                    })
                                }
                            }
                            s4PopularTemplateRow.appendChild(newNode);
                        });
                        if(hasIncompatible){
                            const warningNode = document.createElement("span");
                            warningNode.innerHTML = `Some recipes are not compatible with your txAdmin version.<br> Please update txAdmin to be able to use them.`;
                            warningNode.classList.add('text-danger', 'font-weight-bold', 'ml-3');
                            s4PopularTemplateRow.appendChild(warningNode);
                        }
                    }
                },
                error: function (xmlhttprequest, textstatus, message) {
                    s4PopularTemplateRow.innerText = `Failed to load recipe list. 
                    Please click on the "back" button and try again.`;
                }
            });

        }

        // Deployment type selection
        function selectTemplate(key){
            selectedTemplateIndex = key;
            if(!loadedTemplates[key]){
                return alert('Invalid Template');
            }
            const deployData = buildDeployName(loadedTemplates[key].name);
            s5DeployerTargetInput.value = deployData.path;
            deploymentID = deployData.id;
            s5DeployerTargetInput.disabled = true;
            s5DeployerTargetChangeBtn.classList.remove('d-none');
            stepperInstace.nextStep();
        }

        // Validate a remote template url
        function validateRemoteTemplate(destroyFeedback) {
            const currentSteps = stepperInstace.getSteps();
            s4RemoteTemplateInput.classList.remove('is-invalid', 'is-valid');
            s4RemoteTemplateInputError.classList.add('d-none');

            txAdminAPI({
                type: "POST",
                url: '/setup/validateRecipeURL',
                timeout: REQ_TIMEOUT_LONG,
                data: {recipeURL: s4RemoteTemplateInput.value.trim()},
                success: function (data) {
                    if (checkApiLogoutRefresh(data)) return;
                    if (data.success == true){
                        const deployData = buildDeployName(data.name);
                        s5DeployerTargetInput.value = deployData.path;
                        deploymentID = deployData.id;
                        currentSteps.active.step.classList.remove('wrong');
                        currentSteps.active.step.classList.add('done');
                        s4RemoteTemplateInput.classList.add('is-valid');
                        destroyFeedback(true);
                    }else{
                        stepperInstace.wrongStep();
                        s4RemoteTemplateInputError.innerHTML = '<br><b>Error:</b> <span data-errmsg>Unknown error</span> <br>Make sure this is a valid Recipe URL.';
                        s4RemoteTemplateInputError.querySelector('[data-errmsg]').textContent = data.message ?? 'Unknown error';
                        s4RemoteTemplateInputError.classList.remove('d-none');
                        s4RemoteTemplateInput.classList.add('is-invalid');
                        destroyFeedback(false);
                    }
                },
                error: function (xmlhttprequest, textstatus, message) {
                    stepperInstace.wrongStep();
                    s4RemoteTemplateInputError.innerHTML = '<br><b>Error:</b> <span data-errmsg>Unknown error</span> <br>Make sure this is a valid Recipe URL.';
                    s4RemoteTemplateInputError.querySelector('[data-errmsg]').textContent = message ?? 'Unknown error';
                    s4RemoteTemplateInputError.classList.remove('d-none');
                    s4RemoteTemplateInput.classList.add('is-invalid');
                    destroyFeedback(false);
                }
            });
        }


        //Local deploy path enable
        function s5DeployerTargetEnablePath(){
            s5DeployerTargetInput.disabled = false;
            s5DeployerTargetInput.focus();
            s5DeployerTargetChangeBtn.classList.add('d-none');
        }

        
        // Validate a local deploy path
        function validateLocalDeployPath(destroyFeedback) {
            const currentSteps = stepperInstace.getSteps();
            s5DeployerTargetInput.classList.remove('is-invalid', 'is-valid');
            s5DeployerTargetError.classList.add('d-none');

            txAdminAPI({
                type: "POST",
                url: '/setup/validateLocalDeployPath',
                timeout: REQ_TIMEOUT_LONG,
                data: {deployPath: s5DeployerTargetInput.value.trim()},
                success: function (data) {
                    if (checkApiLogoutRefresh(data)) return;
                    if (data.success == true){
                        currentSteps.active.step.classList.remove('wrong');
                        currentSteps.active.step.classList.add('done');
                        s5DeployerTargetInput.classList.add('is-valid');
                        destroyFeedback(true);
                    }else{
                        stepperInstace.wrongStep();
                        s5DeployerTargetError.innerHTML = '<br><b>Error:</b> <span data-errmsg>Unknown error</span>';
                        s5DeployerTargetError.querySelector('[data-errmsg]').textContent = data.message ?? 'Unknown error';
                        s5DeployerTargetError.classList.remove('d-none');
                        s5DeployerTargetInput.classList.add('is-invalid');
                        destroyFeedback(false);
                    }
                },
                error: function (xmlhttprequest, textstatus, message) {
                    stepperInstace.wrongStep();
                    s5DeployerTargetError.innerHTML = connectErrorMessage;
                    s5DeployerTargetError.classList.remove('d-none');
                    s5DeployerTargetInput.classList.add('is-invalid');
                    destroyFeedback(false);
                }
            });
        }


        // Server Data Folder step validation
        function validateLocalDataFolder(destroyFeedback) {
            const currentSteps = stepperInstace.getSteps();
            s4LocalDataPathInput.classList.remove('is-invalid', 'is-valid');
            s4LocalDataPathInputError.classList.add('d-none');
            s5ServerCFGAutofill.classList.add('d-none');
            s5ServerCFGError.classList.add('d-none');
            s5ServerCFGInput.value = '';

            txAdminAPI({
                type: "POST",
                url: '/setup/validateLocalDataFolder',
                timeout: REQ_TIMEOUT_LONG,
                data: {dataFolder: s4LocalDataPathInput.value.trim()},
                success: function (data) {
                    if (checkApiLogoutRefresh(data)) return;
                    if (data.success == true){
                        currentSteps.active.step.classList.remove('wrong');
                        currentSteps.active.step.classList.add('done');
                        s4LocalDataPathInput.classList.add('is-valid');
                        if(data.detectedConfig){
                            s5ServerCFGAutofill.classList.remove('d-none');
                            s5ServerCFGInput.value = data.detectedConfig;
                        }
                        destroyFeedback(true)
                    }else{
                        if(data.suggestion){
                            s4LocalDataPathInputError.innerHTML = 'The path provided is invalid. <br>But it looks like <code data-suggestion>unknown</code> is correct. <br>Do you want to use it instead?';
                            s4LocalDataPathInputError.querySelector('[data-suggestion]').textContent = data.suggestion ?? 'unknown';
                            suggestions['s4LocalDataPathInput'] = data.suggestion;
                            s4LocalDataPathInputFixBtn.classList.remove('d-none');
                        }else{
                            s4LocalDataPathInputError.textContent = data.message;
                        }
                        s4LocalDataPathInputError.classList.remove('d-none');
                        s4LocalDataPathInput.classList.add('is-invalid');
                        stepperInstace.wrongStep();
                        destroyFeedback(false)
                    }
                },
                error: function (xmlhttprequest, textstatus, message) {
                    s4LocalDataPathInputError.innerHTML = connectErrorMessage;
                    s4LocalDataPathInputError.classList.remove('d-none');
                    destroyFeedback(false)
                }
            });

        }

        // Server CFG File step validation
        function validateCFGFile(destroyFeedback) {
            const currentSteps = stepperInstace.getSteps();
            s5ServerCFGInput.classList.remove('is-invalid', 'is-valid');
            s5ServerCFGError.classList.add('d-none');
            const outData = {
                template: false,
                dataFolder: s4LocalDataPathInput.value.trim(),
                cfgFile: s5ServerCFGInput.value.trim(),
            };
            
            txAdminAPI({
                type: "POST",
                url: '/setup/validateCFGFile',
                timeout: REQ_TIMEOUT_LONG,
                data: outData,
                success: function (data) {
                    if (checkApiLogoutRefresh(data)) return;
                    if (data.success == true){
                        currentSteps.active.step.classList.remove('wrong');
                        currentSteps.active.step.classList.add('done');
                        frmName.classList.add('is-valid');
                        destroyFeedback(true)
                    }else{
                        s5ServerCFGError.innerHTML = convertMarkdown(data.message, true);
                        s5ServerCFGError.classList.remove('d-none');
                        s5ServerCFGInput.classList.add('is-invalid');
                        stepperInstace.wrongStep();
                        destroyFeedback(false)
                    }
                },
                error: function (xmlhttprequest, textstatus, message) {
                    s5ServerCFGError.innerHTML = connectErrorMessage;
                    s5ServerCFGError.classList.remove('d-none');
                    destroyFeedback(false)
                }
            });
        }

        // Save function
        function performSave(destroyFeedback) {
            const saveError = document.getElementById("saveError");
            saveError.classList.add('d-none');

            const outData = {
                name: frmName.value.trim(),
                type: selectedDeploymentType
            };
            if(selectedDeploymentType == 'popular'){
                outData.isTrustedSource = true;
                outData.recipeURL = loadedTemplates[selectedTemplateIndex].url;
                outData.targetPath = s5DeployerTargetInput.value.trim();
                outData.deploymentID = deploymentID;
                
            }else if(selectedDeploymentType == 'remote'){
                outData.isTrustedSource = false;
                outData.recipeURL = s4RemoteTemplateInput.value.trim();
                outData.targetPath = s5DeployerTargetInput.value.trim();
                outData.deploymentID = deploymentID;

            }else if(selectedDeploymentType == 'custom'){
                outData.targetPath = s5DeployerTargetInput.value.trim();
                outData.deploymentID = deploymentID;
                
            }else if(selectedDeploymentType == 'local'){
                outData.dataFolder = s4LocalDataPathInput.value.trim();
                outData.cfgFile = s5ServerCFGInput.value.trim();
                
            }else{
                return alert('Unknown deployment type')
            }
            
            txAdminAPI({
                type: "POST",
                url: '/setup/save',
                timeout: REQ_TIMEOUT_REALLY_LONG,
                data: outData,
                success: function (data) {
                    if (checkApiLogoutRefresh(data)) return;
                    if (data.success == true){
                        navigateParentTo((selectedDeploymentType === 'local') ? '/server/console' : '/server/deployer');
                    }else{
                        saveError.innerHTML = convertMarkdown(`${data.message}\nPlease refresh the page and start again.`, true);
                        saveError.classList.remove('d-none');
                        stepperInstace.wrongStep();
                        destroyFeedback(false)
                    }
                },
                error: function (xmlhttprequest, textstatus, message) {
                    saveError.innerHTML = connectErrorMessage;
                    saveError.classList.remove('d-none');
                    destroyFeedback(false)
                }
            });
        }
    </script>
</body>
</html>
