<script>

import { Button, InputDialog, TopBar, MainLayout } from 'pankow';
import LogsModel from '../models/LogsModel.js';
import AppsModel from '../models/AppsModel.js';

export default {
  name: 'LogsViewer',
  components: {
    Button,
    InputDialog,
    MainLayout,
    TopBar
  },
  data() {
    return {
      accessToken: localStorage.token,
      logsModel: null,
      appsModel: null,
      busyRestart: false,
      showRestart: false,
      showFilemanager: false,
      showTerminal: false,
      id: '',
      name: '',
      type: '',
      downloadUrl: '',
      logLines: []
    };
  },
  methods: {
    onClear() {
      while (this.$refs.linesContainer.firstChild) this.$refs.linesContainer.removeChild(this.$refs.linesContainer.firstChild);
    },
    onDownload() {
      this.logsModel.download();
    },
    async onRestartApp() {
      if (this.type !== 'app') return;

      const confirmed = await this.$refs.inputDialog.confirm({
        message: this.$t('filemanager.toolbar.restartApp') + '?',
        confirmStyle: 'danger',
        confirmLabel: this.$t('main.dialog.yes'),
        rejectLabel: this.$t('main.dialog.no')
      });

      if (!confirmed) return;

      this.busyRestart = true;

      await this.appsModel.restart();

      this.busyRestart = false;
    }
  },
  async mounted() {
    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 id = urlParams.get('id');

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

    this.logsModel = LogsModel.create(this.type, this.id);

    if (this.type === 'app') {
      this.appsModel = AppsModel.create();

      try {
        const app = await this.appsModel.get();
        this.name = `${app.label || app.fqdn} (${app.manifest.title})`;
        this.showFilemanager = !!app.manifest.addons.localstorage;
        this.showTerminal = app.manifest.id !== 'io.cloudron.builtin.appproxy';
        this.showRestart = app.manifest.id !== 'io.cloudron.builtin.appproxy';
      } catch (e) {
        console.error(`Failed to get app info for ${this.id}:`, e);
      }
    }

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

    this.downloadUrl = this.logsModel.getDownloadUrl();

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

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

      for (const line of newLogLines) {
        if (lines < maxLines) ++lines;
        else this.$refs.linesContainer.removeChild(this.$refs.linesContainer.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>`;
        this.$refs.linesContainer.appendChild(logLine);

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

      newLogLines = [];
    }, 500);

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

</script>

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

          <Button style="margin-left: 20px;" :title="$t('filemanager.toolbar.restartApp')" v-show="showRestart" secondary tool :loading="busyRestart" icon="fa-solid fa-arrows-rotate" @click="onRestartApp"/>
          <Button :href="'/terminal.html?id=' + id" target="_blank" v-show="showTerminal" secondary tool icon="fa-solid fa-terminal" :title="$t('terminal.title')" />
          <Button :href="'/filemanager.html#/home/app/' + id" target="_blank" v-show="showFilemanager" secondary tool icon="fa-solid fa-folder" :title="$t('filemanager.title')" />
        </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;
  line-height: 1.2;
  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>

