{% extends 'layout.html'%}

{%block content%}

<br>
<div class="col-md-11">
    <h1>Custom Requests</h1>
    <form id="custom_request_form" class="row g-3">
        <div class="col-2">
            <label for="method" class="form-label">Method *</label>
            <select id="method" placeholder="GET" class="form-select" required>
                <option value="GET">GET</option>
                <option value="POST">POST</option>
                <option value="PUT">PUT</option>
                <option value="PATCH">PATCH</option>
                <option value="HEAD">HEAD</option>
                <option value="DELETE">DELETE</option>
                <option value="OPTIONS">OPTIONS</option>
            </select>
        </div>
        <div class="col-2">
            <label for="request_type" class="form-label">Body type</label>
            <select id="request_type" class="form-select">
                <option value="text">Text</option>
                <option value="urlencoded">URL Encoded</option>
                <option value="json">JSON</option>
                <option value="xml">XML</option>
            </select>
        </div>
        <div class="col-2">
            <label for="access_token_id" class="form-label">Access token id *</label>
            <div class="input-group">
                <input type="text" id="access_token_id" name="access_token_id" class="form-control" required>
                <button class="btn btn-outline-primary" type="button" data-bs-toggle="modal" data-bs-target="#access_token_modal" onclick="$('#access_token_modal_table').DataTable().ajax.reload(null, false)">Select...</button>
            </div>
        </div>
        <div class="col-3"></div>
        <div class="col-3">
            <label for="request_template_name" class="form-label">Request Template</label>
            <div class="input-group">
                <input type="text" id="request_template_name" placeholder="Template Name" class="form-control">
                <button class="btn btn-outline-primary" type="button" onclick="saveRequestTemplate()">Save</button>
                <button class="btn btn-outline-primary" type="button" data-bs-toggle="modal" data-bs-target="#request_template_modal" onclick="$('#request_templates').DataTable().ajax.reload(null, false)">Load...</button>
            </div>
        </div>
        <div>
            <label for="request_uri" class="form-label">Request Uri *</label>
            <input type="text" id="request_uri" placeholder="https://graph.microsoft.com/v1.0/me" class="form-control" required>
        </div>
        <div>
            <button class="btn btn-outline-success" type="button" onclick="addHeaderRow()">Add Header</button>
            <button class="btn btn-outline-success" type="button" onclick="addVariableRow()">Add Variable</button>
        </div>
        <div class="col-6" id="header_fields">
            <div class="input-group">
                <span class="input-group-text">Header</span>
                <input type="text" placeholder="X-Header" class="form-control header_name">
                <input type="text" placeholder="Custom" class="form-control header_value">
                <button class="btn btn-outline-danger" type="button" onclick="return this.parentNode.remove()">Delete</button>
            </div>
        </div>
        <div class="col-6" id="variable_fields">
            <div class="input-group">
                <span class="input-group-text">Variable</span>
                <input type="text" placeholder="$$example_id$$" class="form-control variable_name">
                <input type="text" placeholder="01234567-89ab-cdef-0123-456789abcdef" class="form-control variable_value">
                <button class="btn btn-outline-danger" type="button" onclick="return this.parentNode.remove()">Delete</button>
            </div>
        </div>
        <div>
            <button class="btn btn-outline-primary" type="button" onclick="formatBodyJSON()">Format JSON</button>
            <button class="btn btn-outline-primary" type="button" onclick="formatBodyXML()">Format XML</button>
        </div>
        <div class="form-floating">
            <textarea type="text" id="body" class="form-control" placeholder="Body" style="height: 10em"></textarea>
            <label for="body">Body</label>
        </div>
        <div>
            <button id="request_button" type="Button" class="btn btn-primary" onclick="sendGenerateRequest()">
                <span class="spinner-border spinner-border-sm" aria-hidden="true" style="display: none"></span>
                <span id="button_text">Request</span>
            </button>
        </div>
    </form>
    <script>
        getActiveAccessToken(document.getElementById("custom_request_form").access_token_id)
    </script>
</div>
<br>
<div class="row" id="response-card" style="display: none">
    <div class="col-auto" style="min-width:400px">
        <div class="card mt-3">
            <div class="card-header">
                <div class="d-flex justify-content-between">
                    <div class="btn-group btn-group-sm" role="group">
                        <button type="button" id="response_card_body_button" class="btn btn-outline-primary active" onclick="toggleResponseCardContent()">Body</button>
                        <button type="button" id="response_card_headers_button" class="btn btn-outline-primary" onclick="toggleResponseCardContent()">Headers</button>
                    </div>
                    <b>Response [<span id="response_status_code"></span>]</b>
                    <div></div>
                </div>
            </div>
            <div class="card-body">
                <pre id="response_body" class="mb-0"></pre>
                <div id="response_headers" class="mb-0" style="display: none">
                    <table id="response_header_table" class="table table-striped table-responsive" style="word-wrap: break-word; word-break: break-all; width:100%">
                        <thead>
                            <tr>
                                <th>Response Header</th>
                                <th>Value</th>
                            </tr>
                        </thead>
                    </table>
                </div>
            </div>
        </div>
    </div>
</div>

<script>
    function toggleResponseCardContent() {
        $("#response_card_body_button").toggleClass("active");
        $("#response_card_headers_button").toggleClass("active");
        $("#response_body").toggle();
        $("#response_headers").toggle();
        $("#response_header_table").DataTable().columns.adjust()
    }

    function getInputHeaders() {
        let headers = {};
        for (const header of $("#header_fields").children()) {
            if (header.getElementsByClassName("header_name")[0].value != "") {
                headers[header.getElementsByClassName("header_name")[0].value] = header.getElementsByClassName("header_value")[0].value;
            };
        };
        return headers;
    }
    function getInputVariables() {
        let variables = {};
        for (const variable of $("#variable_fields").children()) {
            if (variable.getElementsByClassName("variable_name")[0].value != "") {
                variables[variable.getElementsByClassName("variable_name")[0].value] = variable.getElementsByClassName("variable_value")[0].value;
            };
        };
        return variables;
    }

    async function sendGenerateRequest() {
        setButtonLoadingState($("#request_button"));
        // Send request
        try {
            let request_form = document.getElementById("custom_request_form");
            let response = await $.ajax({
                type: "POST",
                async: true,
                url: "/api/custom_api_request",
                dataType: "json",
                contentType: "application/json; charset=utf-8",
                data: JSON.stringify({
                    "uri": request_form.request_uri.value,
                    "access_token_id": request_form.access_token_id.value,
                    "method": request_form.method.value,
                    "request_type": request_form.request_type.value,
                    "body": request_form.body.value,
                    "headers": getInputHeaders(),
                    "variables": getInputVariables()
                }),
                success: null,
                error: function (jqXHR, textStatus, errorThrown) {
                    if (jqXHR.status >= 400) {
                        bootstrapAlert(jqXHR.responseText, "danger");
                        return;
                    }
                }
            });
            //let responseJSON = JSON.parse(response.responseText);
            let responseJSON = response;
            try {
                if (responseJSON.response_type == "json") {
                    $("#response_body").html(formatJsonCode(JSON.parse(responseJSON.response_text)));
                    Prism.highlightAll();
                } else if (responseJSON.response_type == "xml") {
                    $("#response_body").text(prettifyXml(responseJSON.response_text));
                } else {
                    $("#response_body").text(responseJSON.response_text);
                }
            } catch (e) {
                $("#response_body").text(responseJSON.response_text);
            }
            $("#response_status_code").text(responseJSON.response_status_code);
            $("#response-card").show();

            generateRespHeadersTable(responseJSON.response_headers);
        } finally {
            resetButtonState($("#request_button"), "Request")
        }
    }

    function generateRespHeadersTable(respHeaders) {
        if ($.fn.dataTable.isDataTable('#response_header_table')) {
            $('#response_header_table').DataTable().destroy();
            $('#response_header_table').empty();
        }
        tableData = [];
        for (const header in respHeaders) {
            tableData.push({ "header": header, "value": respHeaders[header] })
        };
        let respHeadersTable = new DataTable('#response_header_table', {
            data: tableData,
            columns: [
                { data: 'header', title: "Response Header" },
                { data: 'value', title: "Value" }
            ],
            autoWidth: true,
            info: false,
            ordering: false,
            paging: false,
            searching: false
        })
    }

    function saveRequestTemplate() {
        let request_form = document.getElementById("custom_request_form");
        let response;
        // request_template_name
        response = $.ajax({
            type: "POST",
            async: false,
            url: "/api/save_request_template",
            dataType: "json",
            contentType: "application/json; charset=utf-8",
            data: JSON.stringify({
                "template_name": $("#request_template_name").val(),
                "uri": request_form.request_uri.value,
                "method": request_form.method.value,
                "request_type": request_form.request_type.value,
                "body": request_form.body.value,
                "headers": getInputHeaders(),
                "variables": getInputVariables()
            }),
            success: null
        });
        if (response.status >= 400) {
            bootstrapAlert(response.responseText, "danger");
            return;
        }
        bootstrapToast("Save Request Template", response.responseText)
    }

    function formatBodyJSON() {
        try {
            $("#body").val(JSON.stringify(JSON.parse($("#body").val()), undefined, 4));
        } catch (e) {
            bootstrapToast("Format JSON", "[Error] Request body is not valid JSON.")
        }
    }

    function formatBodyXML() {
        try {
            $("#body").val(prettifyXml($("#body").val()), undefined, 4);
        } catch (e) {
            bootstrapToast("Format XML", "[Error] Request body is not valid XML.")
        }
    }

    function addHeaderRow(headerName = "", headerValue = "") {
        var headerWrapper = $('<div class="input-group">' +
            '<span class="input-group-text">Header</span>' +
            '</div>');
        var headerNameInput = $('<input type="text" placeholder="X-Header" class="form-control header_name">');
        headerNameInput.val(headerName);
        var headerValueInput = $('<input type="text" placeholder="Custom" class="form-control header_value">');
        headerValueInput.val(headerValue);
        var headerButton = $('<button class="btn btn-outline-danger" type="button" onclick="return this.parentNode.remove()">Delete</button>');

        headerWrapper.append(headerNameInput);
        headerWrapper.append(headerValueInput);
        headerWrapper.append(headerButton);
        $("#header_fields").append(headerWrapper);
    }
    function addVariableRow(variableName = "", variableValue = "") {
        var variableWrapper = $('<div class="input-group">' +
            '<span class="input-group-text">Variable</span>' +
            '</div>');
        var variableNameInput = $('<input type="text" placeholder="$$example_id$$" class="form-control variable_name">');
        variableNameInput.val(variableName);
        var variableNameValue = $('<input type="text" placeholder="01234567-89ab-cdef-0123-456789abcdef" class="form-control variable_value">');
        variableNameValue.val(variableValue);
        var variableButton = $('<button class="btn btn-outline-danger" type="button" onclick="return this.parentNode.remove()">Delete</button>');

        variableWrapper.append(variableNameInput);
        variableWrapper.append(variableNameValue);
        variableWrapper.append(variableButton);
        $("#variable_fields").append(variableWrapper);
    }

    $("#response-card").on('click', 'i#copy-icon', function (e) {
        copyToClipboard($("#response_body").text());
    })
</script>

<!-- Request Template Modal -->
<div class="modal fade" id="request_template_modal" tabindex="-1" aria-labelledby="request_template_modal_label" aria-hidden="true">
    <div class="modal-dialog modal-xl">
        <div class="modal-content">
            <div class="modal-header">
                <h1 class="modal-title fs-5" id="request_template_modal_label">Request Templates</h1>
                <div style="float: right">
                    <i class="fi fi-br-expand px-3" id="expand-icon" style="cursor: pointer; float: left; opacity: 0.5"></i>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
            </div>
            <div class="modal-body">
                <div id="dTable" class="box-body table-responsive" style="padding:10px;">
                    <table id="request_templates" class="table table-striped" style="width:100%">
                        <thead>
                            <tr>
                                <th></th>
                                <th></th>
                                <th></th>
                                <th>ID</th>
                                <th>Name</th>
                                <th>Body type</th>
                                <th>Method</th>
                                <th>URI</th>
                            </tr>
                        </thead>
                    </table>
                </div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
            </div>
        </div>
    </div>
</div>
<script type="text/javascript" class="init">
    // Populate the request_templates table
    let myTable = new DataTable('#request_templates', {
        ajax: {
            url: '/api/list_request_templates', dataSrc: ""
        },
        columns: [
            {
                className: 'dt-control',
                orderable: false,
                data: null,
                defaultContent: '',
                'width': '40px'
            },
            {
                className: 'active-control',
                orderable: false,
                data: null,
                defaultContent: '<i class="fi fi-br-check" style="cursor: pointer"></i>',
                'width': '40px'
            },
            {
                className: 'delete-control',
                orderable: false,
                data: null,
                defaultContent: '<i class="fi fi-rr-trash" style="cursor: pointer"></i>',
                'width': '40px'
            },
            { data: 'id', 'width': '60px' },
            { data: 'template_name', 'width': '170px' },
            { data: 'request_type', 'width': '150px' },
            { data: 'method', 'width': '100px' },
            { data: 'uri' }
        ],
        order: [[3, 'desc']],
        autoWidth: false
    })

    myTable.on('click', 'td.dt-control', function (e) {
        let tr = e.target.closest('tr');
        let row = myTable.row(tr);

        if (row.child.isShown()) {
            // This row is already open - close it
            row.child.hide();
        }
        else {
            // Open this row
            row.child(formatRequestTemplate(row.data())).show();
        }
    });

    myTable.on('click', 'td.active-control', function (e) {
        let tr = e.target.closest('tr');
        let row = myTable.row(tr);
        request_template_info = row.data();
        $("#request_uri").val(request_template_info.uri);
        $("#method").val(request_template_info.method);
        $("#request_type").val(request_template_info.request_type);
        $("#body").val(request_template_info.body);
        $("#request_template_name").val(request_template_info.template_name);
        $('#header_fields').empty();
        $('#variable_fields').empty();
        for (var header_name in request_template_info.headers) {
            if (request_template_info.headers.hasOwnProperty(header_name)) {
                addHeaderRow(header_name, request_template_info.headers[header_name]);
            }
        }
        for (var variable_name in request_template_info.variables) {
            if (request_template_info.variables.hasOwnProperty(variable_name)) {
                addVariableRow(variable_name, request_template_info.variables[variable_name]);
            }
        }
        $('#request_template_modal').modal('hide');
    });

    myTable.on('click', 'td.delete-control', function (e) {
        let tr = e.target.closest('tr');
        let row = myTable.row(tr);
        if (!confirm("Are you sure you want to delete request template '" + row.data().template_name + "'?")) { return }
        deleteRequestTemplate(row.data().id);
    });

    function formatRequestTemplate(d) {
        var descList = $(
            '<dl>' +
            '<dt>Request Template:</dt>' +
            '</dl>');
        var descDetails = $('<dd></dd>');
        var preText = $('<pre></pre>');
        preText.text(JSON.stringify(d, undefined, 4));
        descDetails.append(preText);
        descList.append(descDetails);
        return descList
    }

    function deleteRequestTemplate(id) {
        let response = $.ajax({
            type: "POST",
            async: false,
            url: "/api/delete_request_template",
            data: { "template_id": id }
        });
        $('#request_templates').DataTable().ajax.reload(null, false);
        bootstrapToast("Delete Request Template", response.responseText)
    }

    $("#request_template_modal").on('click', 'i#expand-icon', function (e) {
        $("#request_template_modal .modal-dialog").toggleClass('modal-xl').toggleClass('modal-fullscreen')
        $("#request_template_modal i#expand-icon").toggleClass('fi-br-expand').toggleClass('fi-br-compress')
    })
</script>

    {%endblock content%}
