<script setup>

import { onMounted, ref, useTemplateRef } from 'vue';
import { Notification, fetcher, SideBar } from 'pankow';
import { API_ORIGIN, TOKEN_TYPES } from './constants.js';
import ProfileModel from './models/ProfileModel.js';
import DashboardModel from './models/DashboardModel.js';
import Headerbar from './components/Headerbar.vue';
import OfflineOverlay from './components/OfflineOverlay.vue';
import AppsView from './views/AppsView.vue';
import AppConfigureView from './views/AppConfigureView.vue';
import AppstoreView from './views/AppstoreView.vue';
import BackupsView from './views/BackupsView.vue';
import BrandingView from './views/BrandingView.vue';
import DomainsView from './views/DomainsView.vue';
import EmailView from './views/EmailView.vue';
import EmailDomainView from './views/EmailDomainView.vue';
import EmailsEventlogView from './views/EmailsEventlogView.vue';
import EventlogView from './views/EventlogView.vue';
import MailboxesView from './views/MailboxesView.vue';
import MailinglistsView from './views/MailinglistsView.vue';
import NetworkView from './views/NetworkView.vue';
import ProfileView from './views/ProfileView.vue';
import ServicesView from './views/ServicesView.vue';
import SettingsView from './views/SettingsView.vue';
import SupportView from './views/SupportView.vue';
import SystemView from './views/SystemView.vue';
import UserDirectoryView from './views/UserDirectoryView.vue';
import UsersView from './views/UsersView.vue';
import VolumesView from './views/VolumesView.vue';

const VIEWS = {
  APPS: 'apps',
  APP: 'app',
  APPSTORE: 'appstore',
  BACKUPS: 'backups',
  BRANDING: 'branding',
  DOMAINS: 'domains',
  EMAIL: 'email',
  EMAIL_DOMAIN: 'email-domain',
  EMAILS_EVENTLOG: 'emails-eventlog',
  EMAILS_MAILBOXES: 'emails-mailboxes',
  EMAILS_MAILINGLISTS: 'emails-mailinglists',
  EVENTLOG: 'eventlog',
  NETWORK: 'network',
  PROFILE: 'profile',
  SERVICES: 'services',
  SETTINGS: 'settings',
  SUPPORT: 'support',
  SYSTEM: 'system',
  USER_DIRECTORY: 'user-directory',
  USERS: 'users',
  VOLUMES: 'volumes',
};

const offlineOverlay = useTemplateRef('offlineOverlay');

function onOnline() {
  ready.value = true;
}

fetcher.globalOptions.errorHook = (error) => {
  // network error, request killed by browser
  if (error instanceof TypeError) {
    ready.value = false;
    return offlineOverlay.value.open();
  }

  // re-login will make the code get a new token
  if (error.status === 401) return profileModel.logout();

  if (error.status === 500 || error.status === 501) {
    // actual internal server error, most likely a bug or timeout log to console only to not alert the user
    if (!ready.value) {
      console.error(error);
      console.log('------\nCloudron Internal Error\n\nIf you see this, please send a mail with above log to support@cloudron.io\n------\n');
    }
  }

  if (error.status >= 502) {
    // This means the box service is not reachable. We just show offline banner for now
    ready.value = false;
    return offlineOverlay.value.open();
  }
};

const dashboardModel = DashboardModel.create();
const profileModel = ProfileModel.create();

const sidebar = useTemplateRef('sidebar');
const ready = ref(false);
const view = ref('');
const profile = ref({});
const subscription = ref({
  plan: {},
});
const config = ref({});

function onSidebarClose() {
  sidebar.value.close();
}

const activeSidebarItem = ref('');
const activeSidebarGroup = ref('');
function onToggleGroup(group) {
  activeSidebarGroup.value = activeSidebarGroup.value === group ? '' : group;
}

function onHashChange() {
  const v = location.hash.slice(2);

  activeSidebarItem.value = v;

  if (activeSidebarItem.value.indexOf('email') === 0) activeSidebarGroup.value = 'email';
  else activeSidebarGroup.value = '';

  if (v === VIEWS.APPS) {
    view.value = VIEWS.APPS;
  } else if (v.indexOf(VIEWS.APPSTORE) === 0 && profile.value.isAtLeastAdmin) {
    view.value = VIEWS.APPSTORE;
  } else if (v.indexOf(VIEWS.APP+'/') === 0) { // this checks permissions within the view as we may have an app operator
    view.value = VIEWS.APP;
  } else if (v === VIEWS.BACKUPS && profile.value.isAtLeastAdmin) {
    view.value = VIEWS.BACKUPS;
  } else if (v === VIEWS.BRANDING && profile.value.isAtLeastAdmin) {
    view.value = VIEWS.BRANDING;
  } else if (v === VIEWS.DOMAINS && profile.value.isAtLeastAdmin) {
    view.value = VIEWS.DOMAINS;
  } else if (v === VIEWS.EMAIL && profile.value.isAtLeastMailManager) {
    view.value = VIEWS.EMAIL;
  } else if (v === VIEWS.EMAILS_EVENTLOG && profile.value.isAtLeastMailManager) {
    view.value = VIEWS.EMAILS_EVENTLOG;
  } else if (v === VIEWS.EMAILS_MAILBOXES && profile.value.isAtLeastMailManager) {
    view.value = VIEWS.EMAILS_MAILBOXES;
  } else if (v === VIEWS.EMAILS_MAILINGLISTS && profile.value.isAtLeastMailManager) {
    view.value = VIEWS.EMAILS_MAILINGLISTS;
  } else if (v.indexOf(VIEWS.EMAIL+'/') === 0 && profile.value.isAtLeastMailManager) {
    view.value = VIEWS.EMAIL_DOMAIN;
  } else if (v === VIEWS.EVENTLOG && profile.value.isAtLeastAdmin) {
    view.value = VIEWS.EVENTLOG;
  } else if (v === VIEWS.NETWORK && profile.value.isAtLeastAdmin) {
    view.value = VIEWS.NETWORK;
  } else if (v.indexOf(VIEWS.PROFILE) === 0) {
    view.value = VIEWS.PROFILE;
  } else if (v === VIEWS.SERVICES && profile.value.isAtLeastAdmin) {
    view.value = VIEWS.SERVICES;
  } else if (v === VIEWS.SETTINGS && profile.value.isAtLeastAdmin) {
    view.value = VIEWS.SETTINGS;
  } else if (v === VIEWS.SUPPORT && profile.value.isAtLeastOwner) {
    view.value = VIEWS.SUPPORT;
  } else if (v === VIEWS.SYSTEM && profile.value.isAtLeastAdmin) {
    view.value = VIEWS.SYSTEM;
  } else if (v === VIEWS.USER_DIRECTORY && profile.value.isAtLeastAdmin) {
    view.value = VIEWS.USER_DIRECTORY;
  } else if (v === VIEWS.USERS && profile.value.isAtLeastUserManager) {
    view.value = VIEWS.USERS;
  } else if (v === VIEWS.VOLUMES && profile.value.isAtLeastAdmin) {
    view.value = VIEWS.VOLUMES;
  } else {
    window.location.hash = '/' + VIEWS.APPS;
  }
}

onMounted(async () => {
  if (!localStorage.token) {
    localStorage.setItem('redirectToHash', window.location.hash);

    // start oidc flow
    window.location.href =  `${API_ORIGIN}/openid/auth?client_id=` + (API_ORIGIN ? TOKEN_TYPES.ID_DEVELOPMENT : TOKEN_TYPES.ID_WEBADMIN) + '&scope=openid email profile&response_type=code token&redirect_uri=' + window.location.origin + '/authcallback.html';

    return;
  }

  let [error, result] = await profileModel.get();
  if (error) return console.error(error);
  profile.value = result;

  [error, result] = await dashboardModel.config();
  if (error) return console.error(error);
  config.value = result;

  // TODO need to be reactive when name or icon changes
  window.document.title = result.cloudronName;
  document.getElementById('favicon').href = `${API_ORIGIN}/api/v1/cloudron/avatar?ts=${Date.now()}`;

  if (profile.value.hasBackgroundImage) {
    window.document.body.style.backgroundImage = `url('${profile.value.backgroundImageUrl}')`;
    window.document.body.classList.add('has-background');
  }

  if (config.value.mandatory2FA && !profile.value.twoFactorAuthenticationEnabled) window.location.hash = `/${VIEWS.PROFILE}?setup2fa`;

  window.addEventListener('hashchange', onHashChange);
  onHashChange();

  ready.value = true;
});

</script>

<template>
  <div style="overflow: hidden; height: 100%;">
    <Notification />
    <OfflineOverlay ref="offlineOverlay" @online="onOnline()"/>

    <Transition name="pankow-animation-pop-up">
      <div v-if="ready" style="display: flex; flex-direction: row; overflow: hidden; height: 100%;">

        <!-- <Sidebar :profile="profile" :config="config"/> -->
        <SideBar v-if="profile.isAtLeastUserManager" ref="sidebar">
          <a href="#/" class="sidebar-logo" @click="onSidebarClose()">
            <img :src="`https://${config.adminFqdn}/api/v1/cloudron/avatar`" width="40" height="40"/> {{ config.cloudronName || 'Cloudron' }}
          </a>
          <div class="sidebar-list">
            <a class="sidebar-item" :class="{ active: activeSidebarItem === 'apps' }" href="#/apps" @click="onSidebarClose()"><i class="fa fa-grip fa-fw"></i> {{ $t('apps.title') }}</a>
            <a class="sidebar-item" :class="{ active: activeSidebarItem === 'appstore' }" v-show="profile.isAtLeastAdmin" href="#/appstore" @click="onSidebarClose()"><i class="fa fa-cloud-download-alt fa-fw"></i> {{ $t('appstore.title') }}</a>
            <a class="sidebar-item" :class="{ active: activeSidebarItem === 'users' }" v-show="profile.isAtLeastUserManager" href="#/users" @click="onSidebarClose()"><i class="fa fa-users fa-fw"></i> {{ $t('main.navbar.users') }}</a>
            <a class="sidebar-item" :class="{ active: activeSidebarItem === 'backups' }" v-show="profile.isAtLeastAdmin" href="#/backups" @click="onSidebarClose()"><i class="fa fa-archive fa-fw"></i> {{ $t('backups.title') }}</a>
            <a class="sidebar-item" :class="{ active: activeSidebarItem === 'branding' }" v-show="profile.isAtLeastAdmin" href="#/branding" @click="onSidebarClose()"><i class="fa fa-passport fa-fw"></i> {{ $t('branding.title') }}</a>
            <a class="sidebar-item" :class="{ active: activeSidebarItem === 'domains' }" v-show="profile.isAtLeastAdmin" href="#/domains" @click="onSidebarClose()"><i class="fa fa-globe fa-fw"></i> {{ $t('domains.title') }}</a>
            <div class="sidebar-item actionable" v-show="profile.isAtLeastMailManager" @click="onToggleGroup('email')"><i class="fa fa-envelope fa-fw"></i> {{ $t('emails.title') }}</div>
            <Transition name="sidebar-item-group-animation">
              <div class="sidebar-item-group" v-if="activeSidebarGroup === 'email'">
                <a class="sidebar-item" :class="{ active: activeSidebarItem === 'emails-mailboxes' }" href="#/emails-mailboxes" @click="onSidebarClose()"><i class="fa fa-inbox fa-fw"></i> {{ $t('email.incoming.mailboxes.title') }}</a>
                <a class="sidebar-item" :class="{ active: activeSidebarItem === 'emails-mailinglists' }" href="#/emails-mailinglists" @click="onSidebarClose()"><i class="fa-solid fa-envelopes-bulk fa-fw"></i> {{ $t('email.incoming.mailinglists.title') }}</a>
                <a class="sidebar-item" :class="{ active: activeSidebarItem === 'email' }" href="#/email" @click="onSidebarClose()"><i class="fa fa-cog fa-fw"></i> {{ $t('emails.title') }} {{ $t('settings.title') }}</a>
              </div>
            </Transition>
            <a class="sidebar-item" :class="{ active: activeSidebarItem === 'eventlog' }" v-show="profile.isAtLeastAdmin" href="#/eventlog" @click="onSidebarClose()"><i class="fa fa-list-alt fa-fw"></i> {{ $t('eventlog.title') }}</a>
            <a class="sidebar-item" :class="{ active: activeSidebarItem === 'network' }" v-show="profile.isAtLeastAdmin" href="#/network" @click="onSidebarClose()"><i class="fas fa-network-wired fa-fw"></i> {{ $t('network.title') }}</a>
            <a class="sidebar-item" :class="{ active: activeSidebarItem === 'services' }" v-show="profile.isAtLeastAdmin" href="#/services" @click="onSidebarClose()"><i class="fa fa-cogs fa-fw"></i> {{ $t('services.title') }}</a>
            <a class="sidebar-item" :class="{ active: activeSidebarItem === 'settings' }" v-show="profile.isAtLeastAdmin" href="#/settings" @click="onSidebarClose()"><i class="fa fa-wrench fa-fw"></i> {{ $t('settings.title') }}</a>
            <a class="sidebar-item" :class="{ active: activeSidebarItem === 'user-directory' }" v-show="profile.isAtLeastAdmin" href="#/user-directory" @click="onSidebarClose()"><i class="fa fa-users-gear fa-fw"></i> {{ $t('users.title') }}</a>
            <a class="sidebar-item" :class="{ active: activeSidebarItem === 'volumes' }" v-show="profile.isAtLeastAdmin" href="#/volumes" @click="onSidebarClose()"><i class="fa fa-hdd fa-fw"></i> {{ $t('volumes.title') }}</a>
            <a class="sidebar-item" :class="{ active: activeSidebarItem === 'system' }" v-show="profile.isAtLeastAdmin" href="#/system" @click="onSidebarClose()"><i class="fa fa-chart-area fa-fw"></i> {{ $t('system.title') }}</a>
          </div>
        </SideBar>

        <div style="flex-grow: 1; display: flex; flex-direction: column; overflow: hidden; height: 100%;">
          <Headerbar :config="config" :subscription="subscription" :profile="profile"/>

          <div style="display: flex; justify-content: center; overflow: auto; flex-grow: 1; padding: 0 6px;">
            <AppsView v-if="view === VIEWS.APPS" />
            <AppConfigureView v-else-if="view === VIEWS.APP" />
            <AppstoreView v-else-if="view === VIEWS.APPSTORE" />
            <BackupsView v-else-if="view === VIEWS.BACKUPS" />
            <BrandingView v-else-if="view === VIEWS.BRANDING" />
            <DomainsView v-else-if="view === VIEWS.DOMAINS" />
            <EmailView v-else-if="view === VIEWS.EMAIL" />
            <EmailDomainView v-else-if="view === VIEWS.EMAIL_DOMAIN" />
            <EmailsEventlogView v-else-if="view === VIEWS.EMAILS_EVENTLOG" />
            <EventlogView v-else-if="view === VIEWS.EVENTLOG" />
            <MailboxesView v-else-if="view === VIEWS.EMAILS_MAILBOXES" />
            <MailinglistsView v-else-if="view === VIEWS.EMAILS_MAILINGLISTS" />
            <NetworkView v-else-if="view === VIEWS.NETWORK" />
            <ProfileView v-else-if="view === VIEWS.PROFILE" />
            <ServicesView v-else-if="view === VIEWS.SERVICES" />
            <SettingsView v-else-if="view === VIEWS.SETTINGS" />
            <SupportView v-else-if="view === VIEWS.SUPPORT" />
            <SystemView v-else-if="view === VIEWS.SYSTEM" />
            <UserDirectoryView v-else-if="view === VIEWS.USER_DIRECTORY" />
            <UsersView v-else-if="view === VIEWS.USERS" />
            <VolumesView v-else-if="view === VIEWS.VOLUMES" />
          </div>
        </div>
      </div>
    </Transition>

  </div>
</template>

<style scoped>

.pankow-sidebar {
  background-color: var(--navbar-background);
  border-right: 1px solid var(--pankow-color-background-hover);
  padding: 22px 10px 10px 10px;
  margin-right: 20px;
}

.sidebar-logo img {
  margin-right: 10px;
  border-radius: var(--pankow-border-radius);
}

.sidebar-logo,
.sidebar-logo:hover {
  display: flex;
  align-items: center;
  color: var(--pankow-text-color);
  text-decoration: none;
  padding-left: 10px;
}

.sidebar-list {
  overflow: auto;
  padding-top: 20px;
  scrollbar-color: transparent transparent;
  scrollbar-width: thin;
}

.sidebar-list:hover {
  scrollbar-color: var(--color-neutral-border) transparent;
}

.sidebar-item {
  display: block;
  color: var(--pankow-text-color);
  border-radius: 3px;
  padding: 10px 15px;
  white-space: nowrap;
}

.sidebar-item i {
  opacity: 0.5;
  margin-right: 10px;
}

.sidebar-item.active {
  color: var(--pankow-color-primary);
  text-decoration: none;
  font-weight: bold;
}

.sidebar-item:hover {
  background-color: #e9ecef;
  text-decoration: none;
}

@media (prefers-color-scheme: dark) {
  .sidebar-item:hover {
    background-color: var(--card-background);
  }
}

.sidebar-item.active i ,
.sidebar-item:hover i {
  opacity: 1;
}

.sidebar-item-group {
  padding-left: 20px;
  height: auto;
  overflow: hidden;
  /* we need height to auto so we animate max-height. needs to be bigger than we need */
  max-height: 300px;
}

.sidebar-item-group-animation-enter-active,
.sidebar-item-group-animation-leave-active {
  transition: all 0.2s linear;
}

.sidebar-item-group-animation-leave-to,
.sidebar-item-group-animation-enter-from {
  transform: translateX(-100px);
  opacity: 0;
  max-height: 0;
}

</style>
