<script setup>

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

import { ref, onMounted, useTemplateRef, inject, computed } from 'vue';
import { Button, Menu, TableView, InputDialog, TextInput } from '@cloudron/pankow';
import Section from '../components/Section.vue';
import GroupDialog from '../components/GroupDialog.vue';
import UsersModel from '../models/UsersModel.js';
import GroupsModel from '../models/GroupsModel.js';
import ProfileModel from '../models/ProfileModel.js';

const usersModel = UsersModel.create();
const groupsModel = GroupsModel.create();
const profileModel = ProfileModel.create();

const actionMenuModel = ref([]);
const actionMenuElement = useTemplateRef('actionMenuElement');

const groupsColumns = {
  name: {
    label: t('users.groups.name'),
    nowrap: true,
    sort: true,
  },
  users: {
    label: t('users.groups.users'),
    sort: true,
    nowrap: true,
    hideMobile: true,
    width: '500px',
  },
  actions: {
    width: '55px',
  }
};

function onGroupActionMenu(group, event) {
  actionMenuModel.value = [{
    icon: 'fa-solid fa-pencil-alt',
    label: t('main.action.edit'),
    action: onEditOrAddGroup.bind(null, group),
  }, {
    separator: true,
  }, {
    icon: 'fa-solid fa-trash-alt',
    label: t('main.action.remove'),
    action: onRemoveGroup.bind(null, group),
  }];

  actionMenuElement.value.open(event, event.currentTarget);
}

const profile = ref({});
const busy = ref(true);
const users = ref([]);
const usersById = ref({});
const groups = ref([]);
const groupsById = ref({});
const roles = ref([]);

const features = inject('features');
const subscriptionRequiredDialog = inject('subscriptionRequiredDialog');

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

async function refreshUsers() {
  const [error, result] = await usersModel.list();
  if (error) return console.error(error);

  usersById.value = {};
  users.value = result;
  result.forEach(user => {
    usersById.value[user.id] = user;
  });
}

async function refreshGroups() {
  const [error, result] = await groupsModel.list();
  if (error) return console.error(error);

  groupsById.value = {};
  groups.value = result;
  result.forEach(group => {
    groupsById.value[group.id] = group;
  });
}

function groupMembers(group) {
  return group.userIds.filter(function (uid) { return !!usersById.value[uid]; }).map(function (uid) { return usersById.value[uid].username || usersById.value[uid].email; }).join(' ');
}

const searchFilter = ref('');

const filteredGroups = computed(() => {
  if (!searchFilter.value) return groups.value;

  return groups.value.filter(g => {
    const search = searchFilter.value.toLowerCase();

    if (g.name.toLowerCase().indexOf(search) !== -1) return true;
    if (groupMembers(g).toLowerCase().indexOf(search) !== -1) return true;

    return false;
  });
});

function onEditOrAddGroup(group = null) {
  if (group || features.value.userGroups) groupDialog.value.open(group);
  else subscriptionRequiredDialog.value.open();
}

async function onRemoveGroup(group) {
  const yes = await inputDialog.value.confirm({
    title: t('users.deleteGroupDialog.title'),
    message: t('users.deleteGroupDialog.description', { name: group.name, memberCount: group.userIds.length }),
    confirmStyle: 'danger',
    confirmLabel: t('users.deleteGroupDialog.deleteAction'),
    rejectLabel: t('main.dialog.cancel'),
    rejectStyle: 'secondary'
  });

  if (!yes) return;

  const [error] = await groupsModel.remove(group.id);
  if (error) console.error(error);

  await refreshGroups();
}

onMounted(async () => {
  const [error, result] = await profileModel.get();
  if (error) return console.error(error);

  profile.value = result;

  await refreshUsers();
  await refreshGroups();

  // Order matters for permissions used in canEdit
  roles.value = [
    { id: 'user', name: t('users.role.user'), disabled: false },
    { id: 'usermanager', name: t('users.role.usermanager'), disabled: false },
    { id: 'mailmanager', name: t('users.role.mailmanager'), disabled: false },
    { id: 'admin', name: t('users.role.admin'), disabled: !profile.value.isAtLeastAdmin },
    { id: 'owner', name: t('users.role.owner'), disabled: !profile.value.isAtLeastOwner }
  ];

  busy.value = false;
});

</script>

<template>
  <div class="content">
    <Menu ref="actionMenuElement" :model="actionMenuModel" />
    <InputDialog ref="inputDialog" />
    <GroupDialog ref="groupDialog" @success="refreshGroups()"/>

    <Section :title="$t('main.navbar.groups')" :title-badge="!features.userGroups ? 'Upgrade' : ''">
      <template #header-title-extra>
        <span style="font-weight: normal; font-size: 14px">({{ busy ? '-' : filteredGroups.length }})</span>
      </template>


      <template #header-buttons>
        <TextInput :placeholder="$t('main.searchPlaceholder')" style="flex-grow: 1;" v-model="searchFilter"/>
        <Button @click="onEditOrAddGroup()">{{ $t('main.action.add') }}</Button>
      </template>

      <TableView :columns="groupsColumns" :model="filteredGroups" :busy="busy" :fixed-layout="true" :placeholder="$t(searchFilter ? 'users.groups.noMatchesPlaceholder' : 'users.groups.emptyPlaceholder')">
        <template #name="group">
          {{ group.name }} &nbsp; <i v-if="group.source" class="far fa-address-book" v-tooltip="$t('users.groups.externalLdapTooltip')"></i>
        </template>
        <template #users="group">{{ groupMembers(group) }}</template>
        <template #actions="group">
          <div style="text-align: right;">
            <Button tool plain secondary @click.capture="onGroupActionMenu(group, $event)" icon="fa-solid fa-ellipsis" />
          </div>
        </template>
      </TableView>
    </Section>
  </div>
</template>

<style scoped>

.group-label {
  padding: 0 5px;
}

</style>
