<!--
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Trigger Information</title>
    <link href="{{nodeModulePath}}/jsoneditor/dist/jsoneditor.min.css" rel="stylesheet" type="text/css">
    <script src="{{nodeModulePath}}/jsoneditor/dist/jsoneditor.min.js"></script>
    <link href="{{webviewTemplatePath}}/css/common.css" rel="stylesheet" type="text/css">
</head>
<body>
    <h2>Trigger Information</h2>
    <table>
        <tr>
            <th>Trigger name</th>
            <td id="name"></td>
        </tr>
        <tr>
            <th>Parameters</th>
            <td>
                <div id="triggerParameters" class="editor"></div>
            </td>
        </tr>
        <tr>
            <th>Annotations</th>
            <td>
                <div id="triggerAnnotations" class="editor"></div>
            </td>
        </tr>
    </table>
    <div>
        <button class="button" onclick="update()">Update trigger</button>
    </div>

    <h2>Connected actions</h2>
    <table id="ruleTable">
        <tr>
            <th>Rule</th>
            <th>Action</th>
        </tr>
    </table>
    <template id="ruleRecord">
        <tr>
            <td class=rule></td>
            <td class=action></td>
        </tr>
    </template>
</body>
<script>
    const vscode = acquireVsCodeApi();
    const parameters = document.getElementById('parameters');
    const triggerName = document.getElementById('name');

    // create the editor instance
    const triggerParameters = document.getElementById("triggerParameters")
    const triggerAnnotations = document.getElementById("triggerAnnotations")
    const editorOption = {
        mode: "code",
        indentation: 4,
        enableSort: false,
        enableTransform: false,
        statusBar: false,
    };
    const paramsEditor = new JSONEditor(triggerParameters, editorOption);
    const annotationsEditor = new JSONEditor(triggerAnnotations, editorOption);

    vscode.postMessage({command: 'initialized'});
    window.addEventListener('message', event => {
        const message = event.data;
        if (message.command === 'getData') {
            setTriggerData(message);
        }
    });

    function update() {
        vscode.postMessage({
            command: 'update',
            parameters: paramsEditor.getText(),
            annotations: annotationsEditor.getText()
        })
    }

    function setTriggerData(state) {
        triggerName.textContent = state.name;

        // set editor contents
        paramsEditor.set(JSON.parse(state.params));
        annotationsEditor.set(JSON.parse(state.annotations));

        let t = document.querySelector('#ruleRecord');
        let tb = document.querySelector('#ruleTable');

        if (state.rules) {
            for (let [name, rule] of Object.entries(state.rules)) {
                let row = document.importNode(t.content, true);
                let td = row.querySelectorAll('td');
                td[0].textContent = name;
                td[1].textContent = rule.action.name;
                tb.appendChild(row);
            }
        }
    }
</script>
</html>
