<script setup>

import { useI18n } from 'vue-i18n';
const i18n = useI18n();
const t = i18n.t;

import { ref, useTemplateRef, onUnmounted, onMounted } from 'vue';
import { Button, InputDialog, TopBar, MainLayout, ButtonGroup } from '@cloudron/pankow';
import LogsModel from '../models/LogsModel.js';
import AppsModel from '../models/AppsModel.js';

const linesContainer = useTemplateRef('linesContainer');
const inputDialog = useTemplateRef('inputDialog');

let logsModel = null;
const appsModel = AppsModel.create();
let refreshInterval = 0;

const busyRestart = ref(false);
const showRestart = ref(false);
const showFilemanager = ref(false);
const showTerminal = ref(false);
const id = ref('');
const name = ref('');
const type = ref('');
const downloadUrl = ref('');

function onClear() {
  while (linesContainer.value.firstChild) linesContainer.value.removeChild(linesContainer.value.firstChild);
}

async function onRestartApp() {
  if (type.value !== 'app') return;

  const confirmed = await inputDialog.value.confirm({
    message: t('filemanager.toolbar.restartApp') + '?',
    confirmLabel: t('main.action.restart'),
    confirmStyle: 'danger',
    rejectLabel: t('main.dialog.cancel'),
    rejectStyle: 'secondary',
  });

  if (!confirmed) return;

  busyRestart.value = true;

  const [error] = await appsModel.restart(id.value);
  if (error) return console.error(error);

  busyRestart.value = false;
}

onMounted(async () => {
  if (!localStorage.token) {
    console.error('Set localStorage.token');
    return;
  }

  const urlParams = new URLSearchParams(window.location.search);
  const appId = urlParams.get('appId');
  const taskId = urlParams.get('taskId');
  const crashId = urlParams.get('crashId');
  const idParam = urlParams.get('id');

  if (appId && taskId) {
    type.value = 'task';
    id.value = taskId;
    name.value = 'Task ' + taskId;
  } else if (appId) {
    type.value = 'app';
    id.value = appId;
    name.value = 'App ' + appId;
  } else if (taskId) {
    type.value = 'task';
    id.value = taskId;
    name.value = 'Task ' + taskId;
  } else if (crashId) {
    type.value = 'crash';
    id.value = crashId;
    name.value = 'Crash ' + crashId;
  } else if (idParam) {
    if (idParam === 'box') {
      type.value = 'platform';
      id.value = idParam;
      name.value = 'Box';
    } else {
      type.value = 'service';
      id.value = idParam;
      name.value = 'Service ' + idParam;
    }
  } else {
    console.error('no supported log type specified');
    return;
  }

  logsModel = LogsModel.create(type.value, id.value, { appId });

  if (type.value === 'app') {
    const [error, app] = await appsModel.get(id.value);
    if (error) return console.error(error);

    name.value = `${app.label || app.fqdn} (${app.manifest.title})`;
    showFilemanager.value = !!app.manifest.addons.localstorage;
    showTerminal.value = app.manifest.id !== 'io.cloudron.builtin.appproxy';
    showRestart.value = app.manifest.id !== 'io.cloudron.builtin.appproxy';
  }

  window.document.title = `Logs Viewer - ${name.value}`;

  downloadUrl.value = logsModel.getDownloadUrl();

  const maxLines = 1000;
  let lines = 0;
  let newLogLines = [];

  const tmp = document.getElementsByClassName('pankow-main-layout-body')[0];
  refreshInterval = setInterval(() => {
    newLogLines = newLogLines.slice(-maxLines);

    for (const line of newLogLines) {
      if (lines < maxLines) ++lines;
      else if (linesContainer.value.firstChild) linesContainer.value.removeChild(linesContainer.value.firstChild);

      const logLine = document.createElement('div');
      logLine.className = 'log-line';
      logLine.innerHTML = `<span class="time">${line.time || '[no timestamp]&nbsp;' }</span> <span>${line.html}</span>`;
      linesContainer.value.appendChild(logLine);

      const autoScroll = tmp.scrollTop > (tmp.scrollHeight - tmp.clientHeight - 34);
      if (autoScroll) setTimeout(() => tmp.scrollTop = tmp.scrollHeight, 1);
    }

    newLogLines = [];
  }, 500);

  logsModel.stream((time, html) => {
    newLogLines.push({ time, html });
  }, function (error) {
    newLogLines.push({ time: error.time, html: error.html });
  });
});

onUnmounted(() => {
  clearInterval(refreshInterval);
});

</script>

<template>
  <MainLayout>
    <template #dialogs>
      <InputDialog ref="inputDialog" />
    </template>
    <template #header>
      <TopBar class="navbar">
        <template #left>
          <span class="title">{{ name }}</span>
        </template>
        <template #right>
          <ButtonGroup>
            <Button icon="fa-solid fa-eraser" @click="onClear()">{{ $t('logs.clear') }}</Button>
            <Button :href="downloadUrl" target="_blank" icon="fa-solid fa-download">{{ $t('logs.download') }}</Button>
          </ButtonGroup>

          <Button style="margin: 0 20px;" v-tooltip="$t('filemanager.toolbar.restartApp')" v-show="showRestart" secondary tool :loading="busyRestart" icon="fa-solid fa-arrows-rotate" @click="onRestartApp"/>

          <ButtonGroup>
            <Button :href="'/terminal.html?id=' + id" target="_blank" v-show="showTerminal" secondary tool icon="fa-solid fa-terminal" v-tooltip="$t('terminal.title')" />
            <Button :href="'/filemanager.html#/home/app/' + id" target="_blank" v-show="showFilemanager" secondary tool icon="fa-solid fa-folder" v-tooltip="$t('filemanager.title')" />
          </ButtonGroup>
        </template>
      </TopBar>
    </template>
    <template #body>
      <div ref="linesContainer"></div>
      <div class="bottom-spacer"></div>
    </template>
  </MainLayout>
</template>

<style>

body {
  background-color: black !important;
}

.title {
  font-size: 20px;
}

.pankow-main-layout-body {
  cursor: text;
}

@media (max-width: 641px) {
  .hide-phone {
    display: none !important;
  }
}

.pankow-top-bar {
  background-color: black;
  color: white;
  margin-bottom: 0 !important;
  padding: 5px 10px;
}

.log-line {
  color: white;
  font-family: monospace;
  font-size: 14px;
  white-space: nowrap;
  width: 100%;
}

.log-line:hover {
    background-color: #333333;
}

.log-line > .time {
  color: #0ff;
  position: sticky;
  left: 0;
  margin-right: 10px;
  background-color: black;
}

.log-line:hover > .time {
    background-color: #333333;
}

.bottom-spacer {
  height: 5px;
}

</style>

