<div class="standardContainer">
    <div class="ui basic segment">
        <h2>HTTP Proxy</h2>
        <p>Proxy HTTP server with HTTP or HTTPS for multiple hosts. If you are only proxying for one host / domain, use Default Site instead.</p>
    </div>
    <style>
        #httpProxyList .ui.toggle.checkbox input:checked ~ label::before{
            background-color: #00ca52 !important;
        }

        .subdEntry td:not(.ignoremw){
            min-width: 200px;
        }
    </style>
    <div style="width: 100%; overflow-x: auto; margin-bottom: 1em; min-height: 300px;">
        <table class="ui celled sortable unstackable compact table">
            <thead>
                <tr>
                    <th>Host</th>
                    <th>Destination</th>
                    <th>Virtual Directory</th>
                    <th style="max-width: 300px;">Advanced Settings</th>
                    <th class="no-sort" style="min-width:150px;">Actions</th>
                </tr>
            </thead>
            <tbody id="httpProxyList">
            
            </tbody>
        </table>
    </div>

    <button class="ui icon right floated basic button" onclick="listProxyEndpoints();"><i class="green refresh icon"></i> Refresh</button>
    <br><br>
</div>

<script>

    /* List all proxy endpoints */
    function listProxyEndpoints(){
        $.get("/api/proxy/list?type=host", function(data){
            $("#httpProxyList").html(``);
            if (data.error !== undefined){
                    $("#httpProxyList").append(`<tr>
                    <td data-label="" colspan="5"><i class="remove icon"></i> ${data.error}</td>
                </tr>`);
            }else if (data.length == 0){
                $("#httpProxyList").append(`<tr>
                    <td data-label="" colspan="5"><i class="green check circle icon"></i> No HTTP Proxy Record</td>
                </tr>`);
            }else{
                //Sort by RootOrMatchingDomain field
                data.sort((a,b) => (a.RootOrMatchingDomain > b.RootOrMatchingDomain) ? 1 : ((b.RootOrMatchingDomain > a.RootOrMatchingDomain) ? -1 : 0))
                data.forEach(subd => {
                    let subdData = encodeURIComponent(JSON.stringify(subd));
                    
                    //Build the upstream list
                    let upstreams = "";
                    if (subd.ActiveOrigins.length == 0){
                        //Invalid config
                        upstreams = `<i class="ui yellow exclamation triangle icon"></i> No Active Upstream Origin<br>`;
                    }else{
                        subd.ActiveOrigins.forEach(upstream => {
                            console.log(upstream);
                            //Check if the upstreams require TLS connections
                            let tlsIcon = "";
                            if (upstream.RequireTLS){
                                tlsIcon = `<i class="green lock icon" title="TLS Mode"></i>`;
                                if (upstream.SkipCertValidations){
                                    tlsIcon = `<i class="yellow lock icon" title="TLS/SSL mode without verification"></i>`
                                }
                            }

                            let upstreamLink = `${upstream.RequireTLS?"https://":"http://"}${upstream.OriginIpOrDomain}`;

                            upstreams += `<a href="${upstreamLink}" target="_blank">${upstream.OriginIpOrDomain} ${tlsIcon}</a><br>`;
                        })
                    }

                    let inboundTlsIcon = "";
                    if ($("#tls").checkbox("is checked")){
                        inboundTlsIcon = `<i class="green lock icon" title="TLS Mode"></i>`;
                        if (subd.BypassGlobalTLS){
                            inboundTlsIcon = `<i class="grey lock icon" title="TLS Bypass Enabled"></i>`;
                        }
                    }else{
                        inboundTlsIcon = `<i class="yellow lock open icon" title="Plain Text Mode"></i>`;
                    }
                    
                    //Build the virtual directory list
                    var vdList = `<div class="ui list">`;
                    subd.VirtualDirectories.forEach(vdir => {
                        vdList += `<div class="item">${vdir.MatchingPath} <i class="green angle double right icon"></i> ${vdir.Domain}</div>`;
                    });
                    vdList += `</div>`;

                    if (subd.VirtualDirectories.length == 0){
                        vdList = `<small style="opacity: 0.3; pointer-events: none; user-select: none;">No Virtual Directory</small>`;
                    }

                    let enableChecked = "checked";
                    if (subd.Disabled){
                        enableChecked = "";
                    }

                    let aliasDomains = ``;
                    if (subd.MatchingDomainAlias != undefined && subd.MatchingDomainAlias.length > 0){
                        aliasDomains = `<small class="aliasDomains" eptuuid="${subd.RootOrMatchingDomain}" style="color: #636363;">Alias: `;
                        subd.MatchingDomainAlias.forEach(alias => {
                            aliasDomains += `<a href="//${alias}" target="_blank">${alias}</a>, `;
                        });
                        aliasDomains = aliasDomains.substr(0, aliasDomains.length - 2); //Remove the last tailing seperator
                        aliasDomains += `</small><br>`;
                    }

                    $("#httpProxyList").append(`<tr eptuuid="${subd.RootOrMatchingDomain}" payload="${subdData}" class="subdEntry">
                        <td data-label="" editable="true" datatype="inbound">
                            <a href="//${subd.RootOrMatchingDomain}" target="_blank">${subd.RootOrMatchingDomain}</a> ${inboundTlsIcon}<br>
                            ${aliasDomains}
                            <small class="accessRuleNameUnderHost" ruleid="${subd.AccessFilterUUID}"></small>
                        </td>
                        <td data-label="" editable="true" datatype="domain">
                            <div class="upstreamList">
                                ${upstreams}        
                            </div>
                        </td>
                        <td data-label="" editable="true" datatype="vdir">${vdList}</td>
                        <td data-label="" editable="true" datatype="advanced" style="width: 350px;">
                            ${subd.AuthenticationProvider.AuthMethod == 0x1?`<i class="ui grey key icon"></i> Basic Auth`:``}
                            ${subd.AuthenticationProvider.AuthMethod == 0x2?`<i class="ui blue key icon"></i> Authelia`:``}
                            ${subd.AuthenticationProvider.AuthMethod == 0x3?`<i class="ui yellow key icon"></i> Oauth2`:``}
                            ${subd.AuthenticationProvider.AuthMethod != 0x0 && subd.RequireRateLimit?"<br>":""}
                            ${subd.RequireRateLimit?`<i class="ui green check icon"></i> Rate Limit @ ${subd.RateLimit} req/s`:``}
                            ${subd.AuthenticationProvider.AuthMethod == 0x0 && !subd.RequireRateLimit?`<small style="opacity: 0.3; pointer-events: none; user-select: none;">No Special Settings</small>`:""}
                        </td>
                        <td class="center aligned ignoremw" editable="true" datatype="action" data-label="">
                            <div class="ui toggle tiny fitted checkbox" style="margin-bottom: -0.5em; margin-right: 0.4em;" title="Enable / Disable Rule">
                                <input type="checkbox" class="enableToggle" name="active" ${enableChecked} eptuuid="${subd.RootOrMatchingDomain}" onchange="handleProxyRuleToggle(this);">
                                <label></label>
                            </div>
                            <button title="Edit Proxy Rule" class="ui circular mini basic icon button editBtn inlineEditActionBtn" onclick='editEndpoint("${(subd.RootOrMatchingDomain).hexEncode()}")'><i class="edit icon"></i></button>
                            <button title="Remove Proxy Rule" class="ui circular mini red basic icon button inlineEditActionBtn" onclick='deleteEndpoint("${(subd.RootOrMatchingDomain).hexEncode()}")'><i class="trash icon"></i></button>
                        </td>
                    </tr>`);
                });
            }

            resolveAccessRuleNameOnHostRPlist();
        });
    }

    //Perform realtime alias update without refreshing the whole page
    function updateAliasListForEndpoint(endpointName, newAliasDomainList){
        let targetEle = $(`.aliasDomains[eptuuid='${endpointName}']`);
        console.log(targetEle);
        if (targetEle.length == 0){
            return;
        }

        let aliasDomains = ``;
        if (newAliasDomainList != undefined && newAliasDomainList.length > 0){
            aliasDomains = `Alias: `;
            newAliasDomainList.forEach(alias => {
                aliasDomains += `<a href="//${alias}" target="_blank">${alias}</a>, `;
            });
            aliasDomains = aliasDomains.substr(0, aliasDomains.length - 2); //Remove the last tailing seperator
            $(targetEle).html(aliasDomains);
            $(targetEle).show();
        }else{
            $(targetEle).hide();
        }
    }

    //Resolve & Update all rule names on host PR list
    function resolveAccessRuleNameOnHostRPlist(){
        //Resolve the access filters
        $.get("/api/access/list", function(data){
            console.log(data);
            if (data.error == undefined){
                //Build a map base on the data
                let accessRuleMap = {};
                for (var i = 0; i < data.length; i++){
                    accessRuleMap[data[i].ID] = data[i];
                }
                
                
                $(".accessRuleNameUnderHost").each(function(){
                    let thisAccessRuleID = $(this).attr("ruleid");
                    if (thisAccessRuleID== ""){
                        thisAccessRuleID = "default"
                    }

                    if (thisAccessRuleID == "default"){
                        //No need to label default access rules
                        $(this).html("");
                        return;
                    }

                    let rule = accessRuleMap[thisAccessRuleID];
                    if (rule == undefined){
                        //Missing config or config too old
                        $(this).html(`<i class="ui red exclamation triangle icon"></i> <b style="color: #db2828;">Access Rule Error</b>`);
                        return;
                    }
                    let icon = `<i class="ui grey filter icon"></i>`;
                    if (rule.ID == "default"){
                        icon = `<i class="ui yellow star icon"></i>`;
                    }else if (rule.BlacklistEnabled && !rule.WhitelistEnabled){
                        //This is a blacklist filter
                        icon = `<i class="ui red filter icon"></i>`;
                    }else if (rule.WhitelistEnabled && !rule.BlacklistEnabled){
                        //This is a whitelist filter
                        icon = `<i class="ui green filter icon"></i>`;
                    }else if (rule.WhitelistEnabled && rule.BlacklistEnabled){
                        //Whitelist and blacklist filter
                        icon = `<i class="ui yellow filter icon"></i>`;
                    }

                    if (rule != undefined){
                        $(this).html(`${icon} ${rule.Name}`);
                    }
                });
            }
        })
    }

    //Update the access rule name on given epuuid, call by hostAccessEditor.html
    function updateAccessRuleNameUnderHost(epuuid, newruleUID){
        $(`tr[eptuuid='${epuuid}'].subdEntry`).find(".accessRuleNameUnderHost").attr("ruleid", newruleUID);
        resolveAccessRuleNameOnHostRPlist();
    }

    
    /*
        Inline editor for httprp.html
    */

    function editEndpoint(uuid) {
        uuid = uuid.hexDecode();
        var row = $('tr[eptuuid="' + uuid + '"]');
        var columns = row.find('td[data-label]');
        var payload = $(row).attr("payload");
        payload = JSON.parse(decodeURIComponent(payload));
        console.log(payload);
        columns.each(function(index) {
            var column = $(this);
            var oldValue = column.text().trim();

            if ($(this).attr("editable") == "false"){
                //This col do not allow edit. Skip
                return;
            }

            // Create an input element based on the column content
            var input;
            var datatype = $(this).attr("datatype");
            if (datatype == "domain"){
                let useStickySessionChecked = "";
                if (payload.UseStickySession){
                    useStickySessionChecked = "checked";
                }
                input = `<button class="ui basic compact tiny button" style="margin-left: 0.4em; margin-top: 1em;" onclick="editUpstreams('${uuid}');"><i class="grey server icon"></i> Edit Upstreams</button>
                <div class="ui divider"></div>
                <div class="ui checkbox" style="margin-top: 0.4em;">
                    <input type="checkbox" class="UseStickySession" ${useStickySessionChecked}>
                    <label>Use Sticky Session<br>
                        <small>Enable stick session on load balancing</small></label>
                </div>

                `;
                column.append(input);
                $(column).find(".upstreamList").addClass("editing");
            }else if (datatype == "vdir"){
                //Append a quick access button for vdir page
                column.append(`<button class="ui basic tiny button" style="margin-left: 0.4em; margin-top: 0.4em;" onclick="quickEditVdir('${uuid}');">
                    <i class="ui yellow folder icon"></i> Edit Virtual Directories
                </button>`);

            }else if (datatype == "advanced"){
                let authProvider = payload.AuthenticationProvider.AuthMethod;
                
                let skipWebSocketOriginCheck = payload.SkipWebSocketOriginCheck;
                let wsCheckstate = "";
                if (skipWebSocketOriginCheck){
                    wsCheckstate = "checked";
                }

                let requireRateLimit = payload.RequireRateLimit;
                let rateLimitCheckState = "";
                if (requireRateLimit){
                    rateLimitCheckState = "checked";
                }
                let rateLimit = payload.RateLimit;
                if (rateLimit == 0){
                    //This value is not set. Make it default to 100
                    rateLimit = 100;
                }
                let rateLimitDisableState = "";
                if (!payload.RequireRateLimit){
                    rateLimitDisableState = "disabled";
                }

                column.empty().append(`
                    <div class="grouped fields authProviderPicker">
                        <label><b>Authentication Provider</b></label>
                        <div class="field">
                            <div class="ui radio checkbox">
                                <input type="radio" value="0" name="authProviderType" ${authProvider==0x0?"checked":""}>
                                <label>None (Anyone can access)</label>
                            </div>
                        </div>
                        <div class="field">
                            <div class="ui radio checkbox">
                                <input type="radio" value="1" name="authProviderType" ${authProvider==0x1?"checked":""}>
                                <label>Basic Auth</label>
                            </div>
                        </div>
                        <div class="field">
                            <div class="ui radio checkbox">
                                <input type="radio" value="2" name="authProviderType" ${authProvider==0x2?"checked":""}>
                                <label>Authelia</label>
                            </div>
                        </div>
                    </div>
                    <button class="ui basic compact tiny button" style="margin-left: 0.4em; margin-top: 0.4em;" onclick="editBasicAuthCredentials('${uuid}');"><i class="ui blue user circle icon"></i> Edit Credentials</button>
                    <button class="ui basic compact tiny button" style="margin-left: 0.4em; margin-top: 0.4em;" onclick="editCustomHeaders('${uuid}');"><i class="heading icon"></i> Custom Headers</button>

                    <div class="ui basic advance segment" style="padding: 0.4em !important; border-radius: 0.4em;">
                        <div class="ui endpointAdvanceConfig accordion" style="padding-right: 0.6em;">
                            <div class="title">
                                <i class="dropdown icon"></i>
                                Security Options
                            </div>
                            <div class="content">
                                <div class="ui checkbox" style="margin-top: 0.4em;">
                                    <input type="checkbox" onchange="handleToggleRateLimitInput();" class="RequireRateLimit" ${rateLimitCheckState}>
                                    <label>Require Rate Limit<br>
                                    <small>Check this to enable rate limit on this inbound hostname</small></label>
                                </div><br>
                                <div class="ui mini right labeled fluid input ${rateLimitDisableState}" style="margin-top: 0.4em;">
                                    <input type="number" class="RateLimit" value="${rateLimit}" min="1" >
                                    <label class="ui basic label">
                                        req / sec / IP
                                    </label>
                                </div>
                            </div>
                        </div>
                    <div>
                `);

                $('.authProviderPicker .ui.checkbox').checkbox();
            } else if (datatype == "ratelimit"){
               
                column.empty().append(`
                    <div class="ui checkbox" style="margin-top: 0.4em;">
                        <input type="checkbox" class="RequireRateLimit" ${checkstate}>
                        <label>Require Rate Limit</label>
                    </div>
                    <div class="ui mini fluid input">
                        <input type="number" class="RateLimit" value="${rateLimit}" placeholder="100" min="1" max="1000" >
                    </div>
                `);

            }else if (datatype == 'action'){
                column.empty().append(`
                <button title="Save" onclick="saveProxyInlineEdit('${uuid.hexEncode()}');" class="ui basic small icon circular button inlineEditActionBtn"><i class="ui green save icon"></i></button>
                <button title="Cancel" onclick="exitProxyInlineEdit();" class="ui basic small icon circular button inlineEditActionBtn"><i class="ui remove icon"></i></button>
                
                `);
            }else if (datatype == "inbound"){
                let originalContent = $(column).html();

                //Check if this host is covered within one of the certificates. If not, show the icon
                let enableQuickRequestButton = true;
                let domains = [payload.RootOrMatchingDomain]; //Domain for getting certificate if needed
                for (var i = 0; i < payload.MatchingDomainAlias.length; i++){
                    let thisAliasName = payload.MatchingDomainAlias[i];
                    domains.push(thisAliasName);
                }

                //Check if the domain or alias contains wildcard, if yes, disabled the get certificate button
                if (payload.RootOrMatchingDomain.indexOf("*") > -1){
                    enableQuickRequestButton = false;
                }
                
                if (payload.MatchingDomainAlias != undefined){
                    for (var i = 0; i < payload.MatchingDomainAlias.length; i++){
                        if (payload.MatchingDomainAlias[i].indexOf("*") > -1){
                            enableQuickRequestButton = false;
                            break;
                        }
                    }
                }

                //encode the domain to DOM
                let certificateDomains = encodeURIComponent(JSON.stringify(domains));
                
                column.empty().append(`${originalContent}
                    <div class="ui divider"></div>
                    <div class="ui checkbox" style="margin-top: 0.4em;">
                        <input type="checkbox" class="BypassGlobalTLS" ${payload.BypassGlobalTLS?"checked":""}>
                        <label>Allow plain HTTP access<br>
                            <small>Allow inbound connections without TLS/SSL</small></label>
                    </div><br>
                    <button class="ui basic compact tiny button" style="margin-left: 0.4em; margin-top: 0.4em;" onclick="editAliasHostnames('${uuid}');"><i class=" blue at icon"></i> Alias</button>
                    <button class="ui basic compact tiny button" style="margin-left: 0.4em; margin-top: 0.4em;" onclick="editAccessRule('${uuid}');"><i class="ui filter icon"></i> Access Rule</button>
                    <button class="ui basic compact tiny ${enableQuickRequestButton?"":"disabled"} button" style="margin-left: 0.4em; margin-top: 0.4em;" onclick="requestCertificateForExistingHost('${uuid}', '${certificateDomains}', this);"><i class="green lock icon"></i> Get Certificate</button>
                `);

                $(".hostAccessRuleSelector").dropdown();
            }else{
                //Unknown field. Leave it untouched
            }
        });

        $(".endpointAdvanceConfig").accordion();
        $("#httpProxyList").find(".editBtn").addClass("disabled");
    }

    //handleToggleRateLimitInput will get trigger if the "require rate limit" checkbox
    // is changed and toggle the disable state of the rate limit input field
    function handleToggleRateLimitInput(){
        let isRateLimitEnabled = $("#httpProxyList input.RequireRateLimit")[0].checked;
        if (isRateLimitEnabled){
            $("#httpProxyList input.RateLimit").parent().removeClass("disabled");
        }else{
            $("#httpProxyList input.RateLimit").parent().addClass("disabled");
        }
    }

    function exitProxyInlineEdit(){
        listProxyEndpoints();
        $("#httpProxyList").find(".editBtn").removeClass("disabled");
    }

    function saveProxyInlineEdit(uuid){
        uuid = uuid.hexDecode();
        var row = $('tr[eptuuid="' + uuid + '"]');
        if (row.length == 0){
            return;
        }
        
        var epttype = "host";
        let useStickySession =  $(row).find(".UseStickySession")[0].checked;
        let authProviderType = $(row).find(".authProviderPicker input[type='radio']:checked").val();
        let requireRateLimit = $(row).find(".RequireRateLimit")[0].checked;
        let rateLimit = $(row).find(".RateLimit").val();
        let bypassGlobalTLS = $(row).find(".BypassGlobalTLS")[0].checked;

        $.cjax({
            url: "/api/proxy/edit",
            method: "POST",
            data: {
                "type": epttype,
                "rootname": uuid,
                "ss":useStickySession,
                "bpgtls": bypassGlobalTLS,
                "authprovider" :authProviderType,
                "rate" :requireRateLimit,
                "ratenum" :rateLimit,
            },
            success: function(data){
                if (data.error !== undefined){
                    msgbox(data.error, false, 6000);
                }else{
                    msgbox("Proxy endpoint updated");
                    listProxyEndpoints();
                }
            }
        })
    }

    //Generic functions for delete rp endpoints 
    function deleteEndpoint(epoint){
        epoint = decodeURIComponent(epoint).hexDecode();
        if (confirm("Confirm remove proxy for :" + epoint + "?")){
            $.cjax({
                url: "/api/proxy/del",
                method: "POST",
                data: {ep: epoint},
                success: function(data){
                    if (data.error == undefined){
                        listProxyEndpoints();
                        msgbox("Proxy Rule Deleted", true);
                        reloadUptimeList();
                    }else{
                        msgbox(data.error, false);
                    }
                }
            })
        }
    }

    
    /* button events */
    function editBasicAuthCredentials(uuid){
        let payload = encodeURIComponent(JSON.stringify({
            ept: "host",
            ep: uuid
        }));
        showSideWrapper("snippet/basicAuthEditor.html?t=" + Date.now() + "#" + payload);
    }

    function editAccessRule(uuid){
        let payload = encodeURIComponent(JSON.stringify({
            ept: "host",
            ep: uuid
        }));
        showSideWrapper("snippet/hostAccessEditor.html?t=" + Date.now() + "#" + payload);
    }

    function editAliasHostnames(uuid){
        let payload = encodeURIComponent(JSON.stringify({
            ept: "host",
            ep: uuid
        }));
        showSideWrapper("snippet/aliasEditor.html?t=" + Date.now() + "#" + payload);
    }

    function quickEditVdir(uuid){
        openTabById("vdir");
        $("#vdirBaseRoutingRule").parent().dropdown("set selected", uuid);
    }

    //Open the custom header editor
    function editCustomHeaders(uuid){
        let payload = encodeURIComponent(JSON.stringify({
            ept: "host",
            ep: uuid
        }));
        showSideWrapper("snippet/customHeaders.html?t=" + Date.now() + "#" + payload);
    }

    //Open the load balance option
    function editUpstreams(uuid){
        let payload = encodeURIComponent(JSON.stringify({
            ept: "host",
            ep: uuid
        }));
        showSideWrapper("snippet/upstreams.html?t=" + Date.now() + "#" + payload);
    }

    function handleProxyRuleToggle(object){
        let endpointUUID = $(object).attr("eptuuid");
        let isChecked = object.checked;
        $.cjax({
            url: "/api/proxy/toggle",
            data: {
                "ep": endpointUUID,
                "enable": isChecked
            },
            success: function(data){
                if (data.error != undefined){
                    msgbox(data.error, false);
                }else{
                    if (isChecked){
                        msgbox("Proxy Rule Enabled");
                    }else{
                        msgbox("Proxy Rule Disabled");
                    }
                    
                }
            }
        })
    }

    /* 
        Certificate Shortcut
    */

    function requestCertificateForExistingHost(hostUUID, RootAndAliasDomains, btn=undefined){
        RootAndAliasDomains = JSON.parse(decodeURIComponent(RootAndAliasDomains))
        let renewDomainKey = RootAndAliasDomains.join(",");
        let preferedACMEEmail = $("#prefACMEEmail").val();
        if (preferedACMEEmail == ""){
            msgbox("Preferred email for ACME registration not set", false);
            return;
        }
        let defaultCA = $("#defaultCA").dropdown("get value");
        if (defaultCA == ""){
            defaultCA = "Let's Encrypt";
        }

        //Check if the root or the alias domain contain wildcard character, if yes, return error
        for (var i = 0; i < RootAndAliasDomains.length; i++){
            if (RootAndAliasDomains[i].indexOf("*") != -1){
                msgbox("Wildcard domain can only be setup via ACME tool", false);
                return;
            }
        }
        
        //Renew the certificate
        renewCertificate(renewDomainKey, false, btn);
    }

    //Bind on tab switch events
    tabSwitchEventBind["httprp"] = function(){
        listProxyEndpoints();
    }
</script>