<script setup lang="ts">
import { onMounted, ref, computed  } from "vue";
import { Terminal } from "xterm"
import { FitAddon } from 'xterm-addon-fit';
import { WebglAddon } from "xterm-addon-webgl"
import { MenuAlt2Icon } from "@heroicons/vue/outline"
import fullPic from "~/assert/fullsc.png"
import arthasLogo from "~/assert/arthas.png"
const { isTunnel = false } = defineProps<{
  isTunnel?: boolean
}>()

let ws: WebSocket | undefined;
let intervalReadKey = -1
const DEFAULT_SCROLL_BACK = 1000
const MAX_SCROLL_BACK = 9999999
const MIN_SCROLL_BACK = 1
const ARTHAS_PORT = isTunnel ? "7777" : "8563"
const ip = ref("")
const port = ref('')
const iframe = ref(true)
const fullSc = ref(true)
const agentID = ref('')
const outputHerf = computed(() => {
  console.log(agentID.value)
  return isTunnel?`proxy/${agentID.value}/arthas-output/`:`/arthas-output/`
})
// const isTunnel = import.meta.env.MODE === 'tunnel'
const fitAddon = new FitAddon();
const webglAddon = new WebglAddon();
let xterm = new Terminal({ allowProposedApi: true })

onMounted(() => {
  ip.value = getUrlParam('ip') ?? window.location.hostname;
  port.value = getUrlParam('port') ?? ARTHAS_PORT;
  if (isTunnel) agentID.value = getUrlParam("agentId") ?? ""
  let _iframe = getUrlParam('iframe')
  if (_iframe && _iframe.trim() !== 'false') iframe.value = false

  startConnect(true);
  window.addEventListener('resize', function () {
    if (ws !== undefined && ws !== null) {
      const { cols, rows } = fitAddon.proposeDimensions()!
      ws.send(JSON.stringify({ action: 'resize', cols, rows: rows }));
      fitAddon.fit();
    }
  });
});

/** get params in url **/
function getUrlParam(name: string) {
  const urlparam = new URLSearchParams(window.location.search)
  return urlparam.get(name)
}

function getWsUri() {
  const host = `${ip.value}:${port.value}`
  if (!isTunnel) return `ws://${host}/ws`;
  const path = getUrlParam("path") ?? 'ws'
  const _targetServer = getUrlParam("targetServer")
  let protocol = location.protocol === 'https:' ? 'wss://' : 'ws://';
  const uri = `${protocol}${host}/${encodeURIComponent(path)}?method=connectArthas&id=${agentID.value}`
  if (_targetServer != null) {
    return uri + '&targetServer=' + encodeURIComponent(_targetServer);
  }
  return uri
}
/** init websocket **/
function initWs(silent: boolean) {
  let uri = getWsUri()
  ws = new WebSocket(uri);
  ws.onerror = function () {
    ws ?? ws!.close();
    ws = undefined;
    !silent && alert('Connect error');
  };
  ws.onopen = function () {
    fullSc.value = true

    let scrollback = getUrlParam('scrollback') ?? '0';

    const { cols, rows } = initXterm(scrollback)
    xterm.onData(function (data) {
      ws?.send(JSON.stringify({ action: 'read', data: data }))
    });
    ws!.onmessage = function (event: MessageEvent) {
      if (event.type === 'message') {
        var data = event.data;
        xterm.write(data);
      }
    };
    ws?.send(JSON.stringify({ action: 'resize', cols, rows }));
    intervalReadKey = window.setInterval(function () {
      if (ws != null && ws.readyState === 1) {
        ws.send(JSON.stringify({ action: 'read', data: "" }));
      }
    }, 30000);
  }
  ws.onclose = function (message) {
    if (intervalReadKey != -1) {
      window.clearInterval(intervalReadKey)
      intervalReadKey = -1
    }
    if (message.code === 2000) {
      alert(message.reason);
    }
  };
}

/** init xterm **/
function initXterm(scrollback: string) {
  let scrollNumber = parseInt(scrollback, 10)
  xterm = new Terminal({
    screenReaderMode: false,
    convertEol: true,
    allowProposedApi: true,
    scrollback: isValidNumber(scrollNumber) ? scrollNumber : DEFAULT_SCROLL_BACK
  });
  xterm.loadAddon(fitAddon)

  xterm.open(document.getElementById('terminal')!);

  xterm.loadAddon(webglAddon)
  fitAddon.fit()
  return {
    cols: xterm.cols,
    rows: xterm.rows
  }
}

function isValidNumber(scrollNumber: number) {
  return scrollNumber >= MIN_SCROLL_BACK &&
    scrollNumber <= MAX_SCROLL_BACK;
}

const connectGuard = (silent: boolean): boolean => {
  if (ip.value.trim() === '' || port.value.trim() === '') {
    alert('Ip or port can not be empty');
    return false;
  }
  if (isTunnel && agentID.value == '') {
    if (silent) {
      return false;
    }
    alert('AgentId can not be empty');
    return false;
  }
  if (ws) {
    alert('Already connected');
    return false;
  }
  return true
}
/** begin connect **/
function startConnect(silent: boolean = false) {
  if (connectGuard(silent)) {
    // init webSocket
    initWs(silent);
  }

}

function disconnect() {
  try {
    ws!.close();
    ws!.onmessage = null;
    ws!.onclose = null;
    ws = undefined;
    xterm.dispose();
    fitAddon.dispose()
    webglAddon.dispose()
    fullSc.value = false
    alert('Connection was closed successfully!');
  } catch {
    alert('No connection, please start connect first.');
  }
}

/** full screen show **/
function xtermFullScreen() {
  var ele = document.getElementById('terminal-card')!;
  requestFullScreen(ele);
  ele.onfullscreenchange = (e: Event) => {
    fitAddon.fit()
  }
}

function requestFullScreen(element: HTMLElement) {
  let requestMethod = element.requestFullscreen;
  if (requestMethod) {
    requestMethod.call(element);
    //@ts-ignore
  } else if (window.ActiveXObject) {
    // @ts-ignore
    var wscript = new ActiveXObject("WScript.Shell");
    if (wscript !== null) {
      wscript.SendKeys("{F11}");
    }
  }
}

</script>

<template>
  <div class="flex flex-col h-[100vh] w-[100vw] resize-none">
    <nav v-if="iframe" class="navbar bg-base-100 md:flex-row flex-col w-[100vw]">
      <div class="navbar-start">
        <div class="dropdown dropdown-start 2xl:hidden">
          <label tabindex="0" class="btn btn-ghost btn-sm">
            <MenuAlt2Icon class="w-6 h-6"></MenuAlt2Icon>
          </label>
          <ul tabindex="0" class="dropdown-content menu shadow bg-base-100">
            <li>
              <a class="hover:text-sky-500 dark:hover:text-sky-400 text-sm" href="https://arthas.aliyun.com/doc"
                target="_blank">Documentation
                <span class="sr-only">(current)</span></a>
            </li>
            <li>
              <a class="hover:text-sky-500 dark:hover:text-sky-400 text-sm"
                href="https://arthas.aliyun.com/doc/arthas-tutorials.html" target="_blank">Online
                Tutorials</a>
            </li>
            <li>
              <a class="hover:text-sky-500 dark:hover:text-sky-400 text-sm" href="https://github.com/alibaba/arthas"
                target="_blank">Github</a>
            </li>
          </ul>
        </div>
        <a href="https://github.com/alibaba/arthas" target="_blank" title="" class="mr-2 w-20"><img
            :src="arthasLogo" alt="Arthas" title="Welcome to Arthas web console"></a>

        <ul class="menu menu-vertical 2xl:menu-horizontal hidden">
          <li>
            <a class="hover:text-sky-500 dark:hover:text-sky-400 text-sm" href="https://arthas.aliyun.com/doc"
              target="_blank">Documentation
              <span class="sr-only">(current)</span></a>
          </li>
          <li>
            <a class="hover:text-sky-500 dark:hover:text-sky-400 text-sm"
              href="https://arthas.aliyun.com/doc/arthas-tutorials.html" target="_blank">Online
              Tutorials</a>
          </li>
          <li>
            <a class="hover:text-sky-500 dark:hover:text-sky-400 text-sm" href="https://github.com/alibaba/arthas"
              target="_blank">Github</a>
          </li>
        </ul>

      </div>
      <div class="navbar-center ">
        <div class=" xl:flex-row form-control"        
        :class="{
          'xl:flex-row':isTunnel,
          'lg:flex-row':!isTunnel
        }">
          <label class="input-group input-group-sm mr-2">
            <span>IP</span>
            <input type="text" placeholder="please enter ip address" class="input input-bordered input-sm "
              v-model="ip" />
          </label>
          <label class="input-group input-group-sm mr-2">
            <span>Port</span>
            <input type="text" placeholder="please enter port" class="input input-sm input-bordered" v-model="port" />
          </label>
          <label v-if="isTunnel" class="input-group input-group-sm mr-2">
            <span>AgentId</span>
            <input type="text" placeholder="please enter AgentId" class="input input-sm input-bordered"
              v-model="agentID" />
          </label>
        </div>
      </div>
      <div class="navbar-end">
        <div class="btn-group   2xl:btn-group-horizontal btn-group-horizontal"
        :class="{
          'md:btn-group-vertical':isTunnel
        }">
          <button
            class="btn btn-sm bg-secondary hover:bg-secondary-focus border-none text-secondary-content focus:bg-secondary-focus normal-case"
            @click.prevent="startConnect(true)">Connect</button>
          <button
            class="btn btn-sm bg-secondary hover:bg-secondary-focus border-none text-secondary-content focus:bg-secondary-focus normal-case"
            @click.prevent="disconnect">Disconnect</button>
          <a class="btn btn-sm bg-secondary hover:bg-secondary-focus border-none text-secondary-content focus:bg-secondary-focus normal-case"
            :href="outputHerf" target="_blank">Arthas Output</a>
        </div>
      </div>
    </nav>
    <div class="w-full h-0 flex-auto bg-black overscroll-auto" id="terminal-card">
      <div id="terminal" class="w-full h-full"></div>
    </div>

    <div title="fullscreen" id="fullSc" class="fullSc" v-if="fullSc">
      <button id="fullScBtn" @click="xtermFullScreen"><img :src="fullPic"></button>
    </div>
  </div>
</template>

<style>
#terminal:-webkit-full-screen {
  background-color: rgb(255, 255, 12);
}

.fullSc {
  z-index: 10000;
  position: fixed;
  top: 25%;
  left: 90%;
}

#fullScBtn {
  border-radius: 17px;
  border: 0;
  cursor: pointer;
  background-color: black;
}
</style>