<!-- eslint-disable no-fallthrough -->
<script setup lang="ts">
import { AddressSpace } from '@/ua/AddressSpace';
import { UANodeSet } from '@/ua/UANodeSet';
import { useStore } from '@/store'
import { ref } from 'vue';
import VDialog from './VDialog.vue'
import JSZip from "jszip";
import YAML from 'yaml'
import { assert } from '@/util/assert';
import { storeToRefs } from 'pinia';
import type { IMappingValue } from '@/ua/IAddressSpace';
import { ServerConfig } from '@/ServerConfig';

const store = useStore()
const newProjectOpen = ref(false);
const newProjectDisabled = ref(false); //Disables buttons while loading project
const serverConfigOpen = ref(false);
const projectType = ref("ua");
const { serverConfig } = storeToRefs(store)


async function exportProject() {
        const zip = new JSZip();
        const fileNames:string[]=[];
        const as=store.addressSpace;
        for(const ns of as.nodesets) {
            fileNames.push(ns.fileName);
            zip.file(ns.fileName, ns.toXML(ns.nameSpaceTable, as.nst).toString());
        }
        store.serverConfig.configData.nodesets = fileNames;
        zip.file("project.json", JSON.stringify(store.serverConfig.configData));
        const mapString=YAML.stringify(as.mapping.values());
        zip.file("mapping.yaml", mapString)
        const blob =await zip.generateAsync({type:'blob'});
        downloadBlob(blob, "project.zip");
}

function downloadBlob(blob: Blob, filename: string) {
  let link = document.createElement('a')
  link.href = window.URL.createObjectURL(blob)
  link.download = filename
  document.body.appendChild(link);
  link.click()
  document.body.removeChild(link);
}

async function newProject() {
  newProjectDisabled.value = true;
  store.addressSpace = new AddressSpace([] as UANodeSet[])
  let nodesets: string[] = [];
  switch (projectType.value) {
    case "emco":
      nodesets.push("nodesets/emco_machine_tools.xml");
    case "machinetool":
      nodesets.push("nodesets/Opc.Ua.MachineTool.Nodeset2.xml");
      nodesets.push("nodesets/Opc.Ua.Machinery.NodeSet2.xml");
      nodesets.push("nodesets/Opc.Ua.Ia.NodeSet2.xml");
      nodesets.push("nodesets/Opc.Ua.Di.NodeSet2.xml");
    case "ua":
      nodesets.push("nodesets/Opc.Ua.NodeSet2.xml");
    default:
      break;
  }
  let as = await AddressSpace.load(nodesets.reverse());
  store.setAddressSpace(as);
  newProjectOpen.value = false;
  newProjectDisabled.value = false;
}

async function handleDrop(e: DragEvent) {
  if (!e.dataTransfer)
    return;
  if(e.dataTransfer.files.length==1 && e.dataTransfer.files[0].name.endsWith(".zip")) {
    loadZip(e.dataTransfer.files[0]);
  }
  else {
    for (const file of e.dataTransfer.files) {
      const xmlString = await file.text();
      assert(store.addressSpace!=null);
      store.addNodeset(UANodeSet.parse(xmlString, file.name, store.addressSpace));
    }
  }
}

async function  loadZip(file: File){
  const zip= await JSZip.loadAsync(file.arrayBuffer())
  const config=ServerConfig.load(JSON.parse(await zip.files["project.json"].async("string")));

  const as=new AddressSpace([]);
  for(const fileName of config.configData.nodesets||[]) {
    as.addNodeset(UANodeSet.parse(await zip.files[fileName].async("string"), fileName, as));
  }
  const mlist=YAML.parse(await zip.files['mapping.yaml'].async("string")) as IMappingValue[];
  const mapping=new Map<string, IMappingValue>();
  for(const entry of mlist) {
    mapping.set(entry.path, entry);
  }
  as.mapping=mapping;
  store.serverConfig=config;
  store.setAddressSpace(as);
}
</script>

<template>
  <div v-if="store.addressSpace">
    <div class="card">
      <div class="card-body" v-if="store.addressSpace">
        <div class="d-flex justify-content-between align-items-center mb-3">
          <h5 class="card-title d-inline">Models</h5>
          <div class="dropdown">
            <button class="btn btn-secondary dropdown-toggle"
                    type="button"
                    data-bs-toggle="dropdown"
                    aria-expanded="false">Project
            </button>
            <ul class="dropdown-menu">
              <li><a class="dropdown-item" href="#" @click="serverConfigOpen = true">Edit Settings</a></li>
              <li><a class="dropdown-item" href="#" @click.prevent="exportProject()">Export Project</a></li>
              <li><a class="dropdown-item" href="#" @click="newProjectOpen = true">New Project</a></li>
            </ul>
          </div>
        </div>
        <p class="card-text">
        <ul class="list-group list-group-flush" v-for="nodeset in store.addressSpace.nodesets"
          v-bind:key="nodeset.models[0].modelUri">
          <div v-for="model in nodeset.models" v-bind:key="model.modelUri">
            <li class="list-group-item">{{ model.modelUri }}</li>
          </div>
        </ul>
        <ul class="list-group list-group-flush" @drop.prevent="handleDrop($event)" dropzone="copy"
          @dragover="$event.preventDefault();">
          <div>
            <li class="list-group-item">(drop .xml nodeset or .zip project file here)</li>
          </div>
        </ul>
        </p>
      </div>
    </div>
  </div>

  <v-dialog :open="newProjectOpen" @cancel="newProjectOpen = false">
    <h5>New project</h5>
    <p></p>
    <div class="form-check">
      <input class="form-check-input" type="radio" name="projectType" id="empty" value="empty" v-model="projectType">
      <label class="form-check-label" for="empty">Empty Namespace</label>
    </div>
    <div class="form-check">
      <input class="form-check-input" type="radio" name="projectType" id="ua" value="ua" v-model="projectType" checked>
      <label class="form-check-label" for="ua">http://opcfoundation.org/UA/ Namespace</label>
    </div>
    <div class="form-check">
      <input class="form-check-input" type="radio" name="projectType" id="machinetool" value="machinetool"
        v-model="projectType">
      <label class="form-check-label" for="machinetool">Machinetool Namespace +dependencies</label>
    </div>
    <div class="form-check">
      <input class="form-check-input" type="radio" name="projectType" id="emco" value="emco" v-model="projectType">
      <label class="form-check-label" for="emco">Full EMCO Project</label>
    </div>
    <div class="btn-group d-flex justify-content-end">
      <button class="btn btn-light" @click="newProjectOpen = false" :disabled="newProjectDisabled">Cancel</button>
      <button class="btn btn-light" @click="newProject()" :disabled="newProjectDisabled">OK</button>
    </div>
  </v-dialog>

  <v-dialog :open="serverConfigOpen" @cancel="serverConfigOpen = false">
    <h5>Server Configuration</h5>
    <p></p>
    <div v-if="serverConfig">
        <div class="input-group mb-3">
          <div class="input-group-prepend">
            <span class="input-group-text" id="inputGroup-sizing-default">Manufacturer Name</span>
            </div>
            <input type="text" class="form-control" aria-label="Default" aria-describedby="inputGroup-sizing-default" v-model="serverConfig.configData.manufacturerName">
        </div>
        <div class="input-group mb-3">
          <div class="input-group-prepend">
            <span class="input-group-text" id="inputGroup-sizing-default">Product Name</span>
            </div>
            <input type="text" class="form-control" aria-label="Default" aria-describedby="inputGroup-sizing-default" v-model="serverConfig.configData.productName">
        </div>
        <div class="input-group mb-3">
          <div class="input-group-prepend">
            <span class="input-group-text" id="inputGroup-sizing-default">Software Version</span>
            </div>
            <input type="text" class="form-control" aria-label="Default" aria-describedby="inputGroup-sizing-default" v-model="serverConfig.configData.softwareVersion">
        </div>
        <div class="input-group mb-3">
          <div class="input-group-prepend">
            <span class="input-group-text" id="inputGroup-sizing-default">Application Name</span>
            </div>
            <input type="text" class="form-control" aria-label="Default" aria-describedby="inputGroup-sizing-default" v-model="serverConfig.configData.applicationName">
        </div>
        <div class="input-group mb-3">
          <div class="input-group-prepend">
            <span class="input-group-text" id="inputGroup-sizing-default">Application Uri</span>
            </div>
            <input type="text" class="form-control" aria-label="Default" aria-describedby="inputGroup-sizing-default" v-model="serverConfig.configData.applicationUri">
        </div>
        <div class="input-group mb-3">
          <div class="input-group-prepend">
            <span class="input-group-text" id="inputGroup-sizing-default">Product Uri</span>
            </div>
            <input type="text" class="form-control" aria-label="Default" aria-describedby="inputGroup-sizing-default" v-model="serverConfig.configData.productUri">
        </div>
        <div class="input-group mb-3">
          <div class="input-group-prepend">
            <span class="input-group-text" id="inputGroup-sizing-default">Port</span>
            </div>
            <input type="text" class="form-control" aria-label="Default" aria-describedby="inputGroup-sizing-default" v-model="serverConfig.configData.port">
        </div>
        <div class="input-group mb-3">
          <div class="input-group-prepend">
            <span class="input-group-text" id="inputGroup-sizing-default">Max Connections Per Endpoint</span>
            </div>
            <input type="text" class="form-control" aria-label="Default" aria-describedby="inputGroup-sizing-default" v-model="serverConfig.configData.maxConnections">
        </div>
        <div class="input-group mb-3">
          <div class="input-group-prepend form-check">
            <input class="form-check-input" type="checkbox" id="checkAllowAnon" v-model="serverConfig.configData.allowAnonymous" />
            <label class="form-check-label" for="checkAllowAnon">Allow Anonymous</label>
          </div>
        </div>
      </div>
      <div class="btn-group d-flex justify-content-end">
        <button class="btn btn-light" @click="serverConfigOpen = false">OK</button>
      </div>
  </v-dialog>
</template>


<style></style>