<script setup>

import { ref, reactive, onMounted, onUnmounted, watch } from 'vue';
import moment from 'moment';
import { Button, TextInput, MultiSelect } from '@cloudron/pankow';
import { useDebouncedRef, copyToClipboard } from '@cloudron/pankow/utils';
import AppsModel from '../models/AppsModel.js';
import EventlogsModel from '../models/EventlogsModel.js';
import { eventlogDetails, eventlogSource } from '../utils.js';

const appsModel = AppsModel.create();
const eventlogsModel = EventlogsModel.create();

function getApp(id) {
  return apps.value.find(a => a.id === id);
}

const availableActions = [
  { id: 'app.backup' },
  { id: 'app.backup.finish' },
  { id: 'app.configure' },
  { id: 'app.install' },
  { id: 'app.restore' },
  { id: 'app.uninstall' },
  { id: 'app.update' },
  { id: 'app.update.finish' },
  { id: 'app.login' },
  { id: 'app.oom' },
  { id: 'app.down' },
  { id: 'app.up' },
  { id: 'app.start' },
  { id: 'app.stop' },
  { id: 'app.restart' },
  { id: 'backup.cleanup' },
  { id: 'backup.cleanup.finish' },
  { id: 'backup.finish' },
  { id: 'backup.start' },
  { id: 'branding.avatar' },
  { id: 'branding.footer' },
  { id: 'branding.name' },
  { id: 'certificate.new' },
  { id: 'certificate.renew' },
  { id: 'certificate.cleanup' },
  { id: 'cloudron.activate' },
  { id: 'cloudron.provision' },
  { id: 'cloudron.restore' },
  { id: 'cloudron.start' },
  { id: 'cloudron.update' },
  { id: 'cloudron.update.finish' },
  { id: 'dashboard.domain.update' },
  { id: 'directoryserver.configure' },
  { id: 'dyndns.update' },
  { id: 'domain.add' },
  { id: 'domain.update' },
  { id: 'domain.remove' },
  { id: 'externalldap.configure' },
  { id: 'group.add' },
  { id: 'group.update' },
  { id: 'group.remove' },
  { id: 'mail.location' },
  { id: 'mail.enabled' },
  { id: 'mail.box.add' },
  { id: 'mail.box.update' },
  { id: 'mail.box.remove' },
  { id: 'mail.list.add' },
  { id: 'mail.list.update' },
  { id: 'mail.list.remove' },
  { id: 'service.configure' },
  { id: 'service.rebuild' },
  { id: 'service.restart' },
  { id: 'support.ticket' },
  { id: 'support.ssh' },
  { id: 'user.add' },
  { id: 'user.login' },
  { id: 'user.login.ghost' },
  { id: 'user.logout' },
  { id: 'user.remove' },
  { id: 'user.transfer' },
  { id: 'user.update' },
  { id: 'userdirectory.profileconfig.update' },
  { id: 'volume.add' },
  { id: 'volume.update' },
  { id: 'volume.remove' },
];

const refreshBusy = ref(false);
const apps = ref([]);
const eventlogs = ref([]);
const search = useDebouncedRef('');
const page = ref(1);
const perPage = ref(40);
const actions = reactive([]);

async function onRefresh() {
  refreshBusy.value = true;
  page.value = 1;

  const [error, result] = await eventlogsModel.search(actions.join(','), search.value, page.value, perPage.value);
  if (error) return console.error(error);

  eventlogs.value = result.map(e => {
    return {
      id: Symbol(),
      raw: e,
      details: eventlogDetails(e, e.appId ? getApp(e.appId) : null),
      source: eventlogSource(e, e.appId ? getApp(e.appId) : null)
    };
  });

  refreshBusy.value = false;
}

async function onScroll(event) {
  if (event.target.scrollTop + event.target.clientHeight >= event.target.scrollHeight) {
    page.value++;
    const [error, result] = await eventlogsModel.search(actions.join(','), search.value, page.value, perPage.value);
    if (error) return console.error(error);

    eventlogs.value = eventlogs.value.concat(result.map(e => {
      return {
        id: Symbol(),
        raw: e,
        details: eventlogDetails(e, e.appId ? getApp(e.appId) : null),
        source: eventlogSource(e, e.appId ? getApp(e.appId) : null)
      };
    }));
  }
}

function onCopySource(eventlog) {
  copyToClipboard(eventlog.raw.source.ip);
  window.pankow.notify({ type: 'success', text: 'Copied' });
}

watch(actions, onRefresh);
watch(search, onRefresh);

async function onHashChange() {
  const params = new URLSearchParams(window.location.hash.slice(window.location.hash.indexOf('?')));
  search.value = params.get('search') || '';
}

onMounted(async () => {
  const [error, result] = await appsModel.list();
  if (error) console.error(error);
  else apps.value = result;

  window.addEventListener('hashchange', onHashChange);
  onHashChange();
  if (!search.value) onRefresh();
});

onUnmounted(() => {
  window.removeEventListener('hashchange', onHashChange);
});

</script>

<template>
  <div class="content-large" style="height: 100%; overflow: hidden; display: flex; flex-direction: column;">
    <!-- cant use Section component as we need control over vertical scrolling -->
    <div class="section" style="overflow: hidden; display: flex; flex-direction: column;">
      <h1 class="section-header">
        {{ $t('eventlog.title') }}
        <div>
          <TextInput :placeholder="$t('main.searchPlaceholder')" style="flex-grow: 1;" v-model="search"/>
          <MultiSelect :search-threshold="10" v-model="actions" :options="availableActions" option-label="id" option-key="id" :selected-label="actions.length ? $t('main.multiselect.selected', { n: actions.length }) : $t('eventlog.filterAllEvents')"/>
          <Button tool secondary @click="onRefresh()" :loading="refreshBusy" icon="fa-solid fa-sync-alt" />
        </div>
      </h1>
      <div class="section-body" style="overflow: auto; margin-top: 10px; padding-top: 0px" @scroll="onScroll">
        <table class="eventlog-table">
          <thead>
            <tr>
              <th>{{ $t('eventlog.time') }}</th>
              <th></th>
              <th>{{ $t('eventlog.source') }}</th>
              <th>{{ $t('eventlog.details') }}</th>
            </tr>
          </thead>
          <tbody>
            <template v-for="eventlog in eventlogs" :key="eventlog.id">
              <tr @click="eventlog.isOpen = !eventlog.isOpen" :class="{ 'active': eventlog.isOpen }" >
                <td style="white-space: nowrap;">{{ moment(eventlog.raw.creationTime).format('DD.MM.YYYY') }}</td>
                <td style="white-space: nowrap;">{{ moment(eventlog.raw.creationTime).format('HH:mm:SS') }}</td>
                <td>{{ eventlog.source }}</td>
                <td v-html="eventlog.details"></td>
              </tr>
              <tr v-show="eventlog.isOpen">
                <td colspan="4" class="eventlog-details">
                  <div v-if="eventlog.raw.source.ip" class="eventlog-source" @click="onCopySource(eventlog)">{{ eventlog.raw.source.ip }}</div>
                  <pre>{{ JSON.stringify(eventlog.raw.data, null, 4) }}</pre>
                </td>
              </tr>
            </template>
          </tbody>
        </table>
      </div>
    </div>
  </div>
</template>

<style scoped>


</style>
