<script setup>

import { marked } from 'marked';
import { eachLimit } from 'async';
import { ref, onMounted, inject, useTemplateRef } from 'vue';
import { Button, ButtonGroup, ProgressBar } from '@cloudron/pankow';
import { prettyDate } from '@cloudron/pankow/utils';
import Section from '../components/Section.vue';
import NotificationSettingsDialog from '../components/NotificationSettingsDialog.vue';
import NotificationsModel from  '../models/NotificationsModel.js';

const notificationsModel = NotificationsModel.create();

const busy = ref(true);
const notifications = ref([]);
const notificationsAllBusy = ref(false);
const refreshNotifications = inject('refreshNotifications');
const showAll = ref(false);
const hasMore = ref(true);

let page = 1;

// keep in-sync with NotificationsModel.js
const PAGE_SIZE = 100;

async function refresh() {
  const [error, result] = await notificationsModel.list(showAll.value ? null : false);
  if (error) return console.error(error);

  hasMore.value = result.length >= PAGE_SIZE;
  notifications.value = result;
}

function onToggleActive(notification) {
  notification.active = !notification.active;
}

async function onMarkNotificationRead(notification) {
  notification.busy = true;
  const [error] = await notificationsModel.update(notification.id, true);
  if (error) return console.error(error);

  notification.busy = false;
  notification.acknowledged = true;
  refreshNotifications();

  if (!showAll.value) {
    setTimeout(() => {
      const idx = notifications.value.findIndex(n => n.id === notification.id);
      if (idx === -1) return;
      notifications.value.splice(idx, 1);
    }, 500);
  }
}

async function onMarkNotificationUnread(notification) {
  notification.busy = true;
  const [error] = await notificationsModel.update(notification.id, false);
  if (error) return console.error(error);

  notification.busy = false;
  notification.acknowledged = false;
  refreshNotifications();
}

async function onMarkAllNotificationRead() {
  notificationsAllBusy.value = true;

  await eachLimit(notifications.value.filter(n => !n.acknowledged), 5, async (notification) => {
    notification.busy = true;
    const [error] = await notificationsModel.update(notification.id, true);
    if (error) return console.error(error);
  });

  await refresh();
  refreshNotifications();

  notificationsAllBusy.value = false;
}

function onSetShowAll(value) {
  showAll.value = value;
  hasMore.value = true;
  page = 1;
  refresh();
}

async function onLoadMore() {
  if (!hasMore.value || busy.value) return;

  busy.value = true;
  page++;

  const [error, result] = await notificationsModel.list(showAll.value ? null : false, page);
  if (error) return console.error(error);

  hasMore.value = result.length >= PAGE_SIZE;
  notifications.value = notifications.value.concat(result);

  busy.value = false;
}

async function onScroll(event) {
  if (event.target.scrollTop + event.target.clientHeight >= event.target.scrollHeight) await onLoadMore();
}

const notificationListContainer = useTemplateRef('notificationListContainer');
const notificationSettingsDialog = useTemplateRef('notificationSettingsDialog');
function onOpenSettings() {
  notificationSettingsDialog.value.open();
}

onMounted(async () => {
  await refresh();

  busy.value = false;
});

</script>

<template>
  <div class="content" style="height: 100%; overflow: hidden; display: flex; flex-direction: column;">
    <NotificationSettingsDialog ref="notificationSettingsDialog"/>

    <Section :title="$t('notifications.title')" style="overflow: hidden; display: flex; flex-direction: column;">
      <template #filter-bar>
        <ButtonGroup>
          <Button :outline="showAll ? true : undefined" @click="onSetShowAll(false)">{{ $t('notifications.showUnread') }}</Button>
          <Button :outline="showAll ? undefined : true" @click="onSetShowAll(true)">{{ $t('notifications.showAll') }}</Button>
        </ButtonGroup>
      </template>
      <template #header-buttons>
        <Button secondary @click="onMarkAllNotificationRead()" :loading="notificationsAllBusy" :disabled="notificationsAllBusy">{{ $t('notifications.markAllAsRead') }}</Button>
        <Button @click="onOpenSettings" icon="fa fa-screwdriver-wrench" tool/>
      </template>

      <ProgressBar v-if="busy" mode="indeterminate" :show-label="false" :slim="true" :show-track="false"/>

      <div v-if="!busy && notifications.length === 0" class="empty-placeholder">{{ $t('notifications.allCaughtUp') }}</div>

      <div ref="notificationListContainer" class="notification-list" @scroll="onScroll">
        <div v-for="notification in notifications" :key="notification.id" class="notification-item" :class="{ new: !notification.acknowledged, active: notification.active }">
          <div class="notification-item-title" @click="onToggleActive(notification)">
            <div>
              {{ notification.title }}
              <div class="notification-item-date">{{ prettyDate(notification.creationTime) }}</div>
            </div>
            <div class="read-state-button">
              <Button v-if="notification.type === 'reboot'" href="/#/server">{{ $t('main.action.reboot') }}</Button>
              <Button v-if="notification.acknowledged" plain secondary :disabled="notification.busy" @click.stop="onMarkNotificationUnread(notification)">{{ $t('notifications.markUnread') }}</Button>
              <Button v-else plain secondary :disabled="notification.busy" @click.stop="onMarkNotificationRead(notification)">{{ $t('notifications.markRead') }}</Button>
            </div>
          </div>
          <div class="notification-item-message">
            <div style="cursor: auto; overflow: auto;" v-html="marked.parse(notification.message)"></div>
          </div>
        </div>
      </div>

    </Section>
  </div>
</template>

<style scoped>

.notification-list {
  display: flex;
  gap: 10px;
  flex-direction: column;
  padding-bottom: 10px;
  overflow-y: auto;
  flex: 1;
}

.notification-item {
  cursor: pointer;
  border-radius: 10px;
}

.notification-item.new {
  background-color: var(--navbar-background);
}

.notification-item:hover {
  background-color: var(--pankow-color-background-hover);
}

.notification-item-title {
  font-size: 14px;
  padding: 10px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-weight: var(--pankow-font-weight-bold);
}

.notification-item-date {
  font-size: 12px;
  padding-top: 5px;
  color: gray;
}

.notification-item-message {
  display: none;
  padding-bottom: 10px;
  padding-left: 10px;
  padding-right: 10px;
}

.notification-item.active .notification-item-message {
  display: block;
}

.read-state-button {
  display: none;
  gap: 5px;
}

.notification-item:hover .read-state-button {
  display: flex;
}

.empty-placeholder {
  text-align: center;
  margin-top: 60px;
}

</style>
