
<script setup>

import { ref, onMounted, useTemplateRef, computed } from 'vue';
import { Button, InputDialog, Dialog, FormGroup, Switch } from '@cloudron/pankow';
import { prettyDecimalSize } from '@cloudron/pankow/utils';
import SaveIndicator from '../components/SaveIndicator.vue';
import Section from '../components/Section.vue';
import SettingsItem from '../components/SettingsItem.vue';
import MailServerLocation from '../components/MailServerLocation.vue';
import DomainsModel from '../models/DomainsModel.js';
import MailModel from '../models/MailModel.js';
import ServicesModel from '../models/ServicesModel.js';

const domainsModel = DomainsModel.create();
const mailModel = MailModel.create();
const servicesModel = ServicesModel.create();

const inputDialog = useTemplateRef('inputDialog');
const domains = ref([]);

const maxEmailSizeBusy = ref(false);
const maxEmailSize = ref(0);
const currentMaxEmailSize = ref(0);

async function onChangeMaxEmailSize() {
  maxEmailSizeBusy.value = true;

  const [error] = await mailModel.setMaxEmailSize(parseInt(maxEmailSize.value));
  if (error) return console.error(error);

  currentMaxEmailSize.value = maxEmailSize.value;
  maxEmailSizeBusy.value = false;
}


const aclDialog = useTemplateRef('aclDialog');
const dnsblZonesError = ref('');
const dnsblZonesBusy = ref(false);
const dnsblZones = ref([]);
const dnsblZonesString = ref('');

const dnsblZonesCount = computed(() => {
  return dnsblZones.value.filter(l => l.indexOf('#') !== 0).length;
});

function onShowAclDialog() {
  dnsblZonesError.value = '';
  dnsblZonesBusy.value = false;
  aclDialog.value.open();
}

async function onSubmitAcl() {
  dnsblZonesError.value = '';
  dnsblZonesBusy.value = true;

  const zones = dnsblZonesString.value.split('\n').filter((l) => { return l !== ''; });

  const [error] = await mailModel.setDnsblConfig(zones);
  if (error) {
    dnsblZonesError.value = error.body ? error.body.message : 'Internal error';
    dnsblZonesBusy.value = false;
    return console.error(error);
  }

  aclDialog.value.close();

  dnsblZones.value = zones;
  dnsblZonesBusy.value = false;
}

const mailboxSharingEnabled = ref(false);
const mailboxSharingSaveIndicator = useTemplateRef('mailboxSharingSaveIndicator');

async function onChangeMailboxSharing(value) {
  const [error] = await mailModel.setMailboxSharing(value);
  if (error) {
    mailboxSharingEnabled.value = !value;
    mailboxSharingSaveIndicator.value.error();
    return console.error(error);
  }
  mailboxSharingSaveIndicator.value.success();
}


const virtualAllMailEnabled = ref(false);
const virtualAllMailSaveIndicator = useTemplateRef('virtualAllMailSaveIndicator');

async function onChangeVirtualAllMail(value) {
  const [error] = await mailModel.setVirtualAllMail(value);
  if (error) {
    virtualAllMailEnabled.value = !value;
    virtualAllMailSaveIndicator.value.error();
    return console.error(error);
  }
  virtualAllMailSaveIndicator.value.success();
}


const ftsEnabled = ref(false);
const hasMailServiceSufficientMemory = ref(false);
const ftsSaveIndicator = useTemplateRef('ftsSaveIndicator');

async function onChangeFts(value) {
  const [error] = await mailModel.setFtsConfig(value);
  if (error) {
    ftsEnabled.value = !value;
    ftsSaveIndicator.value.error();
    return console.error(error);
  }
  ftsSaveIndicator.value.success();
}


const spamFilterDialog = useTemplateRef('spamFilterDialog');
const spamFilterBusy = ref(false);
const spamFilterError = ref({});
const blocklist = ref([]);
const blocklistString = ref('');
const allowlist = ref([]);
const allowlistString = ref('');
const spamCustomConfig = ref('');

const blocklistCount = computed(() => {
  return blocklist.value.filter(l => l.trim()).filter(l => l.indexOf('#') !== 0).length;
});

function onShowSpamFilterDialog() {
  spamFilterError.value = {};
  spamFilterBusy.value = false;
  blocklistString.value = blocklist.value.join('\n');
  allowlistString.value = allowlist.value.join('\n');

  spamFilterDialog.value.open();
}

async function onSubmitSpamFilter() {
  spamFilterError.value = {};
  spamFilterBusy.value = true;

  const block = blocklistString.value.split('\n').filter((l) => { return l !== ''; });
  const allow = allowlistString.value.split('\n').filter((l) => { return l !== ''; });

  let [error] = await mailModel.setSpamAcl(allow, block);
  if (error) {
    spamFilterError.value.blocklist = error.body ? error.body.message : 'Internal error';
    spamFilterBusy.value = false;
    return;
  }

  [error] = await mailModel.setSpamCustomConfig(spamCustomConfig.value);
  if (error) {
    spamFilterError.value.config = error.body ? error.body.message : 'Internal error';
    spamFilterBusy.value = false;
    return;
  }

  spamFilterDialog.value.close();

  blocklist.value = block;
  allowlist.value = allow;
  spamFilterBusy.value = false;
}

onMounted(async () => {
  let [error, result] = await domainsModel.list();
  if (error) return console.error(error);

  domains.value = result;

  [error, result] = await mailModel.mailboxSharing();
  if (error) return console.error(error);
  mailboxSharingEnabled.value = result;

  [error, result] = await mailModel.virtualAllMail();
  if (error) return console.error(error);
  virtualAllMailEnabled.value = result;

  [error, result] = await mailModel.maxEmailSize();
  if (error) return console.error(error);
  maxEmailSize.value = result;
  currentMaxEmailSize.value = result;

  [error, result] = await mailModel.dnsblConfig();
  if (error) return console.error(error);
  dnsblZones.value = result;
  dnsblZonesString.value = result.join('\n');

  [error, result] = await mailModel.spamCustomConfig();
  if (error) return console.error(error);
  spamCustomConfig.value = result;

  [error, result] = await mailModel.spamAcl();
  if (error) return console.error(error);
  allowlist.value = result.allowlist;
  blocklist.value = result.blocklist;

  [error, result] = await mailModel.ftsConfig();
  if (error) return console.error(error);
  ftsEnabled.value = result.enabled;

  [error, result] = await servicesModel.get('mail');
  if (error) return console.error(error);
  hasMailServiceSufficientMemory.value = result.config.memoryLimit >= 3221225472; // we need at least 3GB
});

</script>

<template>
  <div class="content">
    <InputDialog ref="inputDialog"/>

    <Dialog ref="aclDialog"
      :title="$t('emails.aclDialog.title')"
      :reject-label="$t('main.dialog.cancel')"
      :reject-active="!dnsblZonesBusy"
       reject-style="secondary"
      :confirm-label="$t('main.dialog.save')"
      :confirm-busy="dnsblZonesBusy"
      @confirm="onSubmitAcl()"
    >
      <form @submit.prevent="onSubmitAcl()" autocomplete="off">
        <fieldset :disabled="dnsblZonesBusy">
          <input type="submit" style="display: none"/>

          <FormGroup>
            <label for="dnsblZonesInput">{{ $t('emails.aclDialog.dnsblZones') }} <sup><a href="https://docs.cloudron.io/email/#dnsbl" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
            <div description>{{ $t('emails.aclDialog.dnsblZonesInfo') }}</div>
            <textarea id="dnsblZonesInput" v-model="dnsblZonesString" :placeholder="$t('emails.aclDialog.dnsblZonesPlaceholder')" rows="4"></textarea>
            <div class="error-label" v-if="dnsblZonesError">{{ dnsblZonesError }}</div>
          </FormGroup>
        </fieldset>
      </form>
    </Dialog>

    <Dialog ref="spamFilterDialog"
      :title="$t('emails.spamFilterDialog.title')"
      :reject-label="$t('main.dialog.cancel')"
      :reject-active="!spamFilterBusy"
       reject-style="secondary"
      :confirm-label="$t('main.dialog.save')"
      :confirm-busy="spamFilterBusy"
      @confirm="onSubmitSpamFilter()"
    >
      <form @submit.prevent="onSubmitSpamFilter()" autocomplete="off">
        <fieldset :disabled="spamFilterBusy">
          <input type="submit" style="display: none"/>

          <FormGroup>
            <label for="blocklistInput">{{ $t('emails.spamFilterDialog.blacklisteAddresses') }}</label>
            <div description>{{ $t('emails.spamFilterDialog.blacklisteAddressesInfo') }}</div>
            <textarea id="blocklistInput" v-model="blocklistString" :placeholder="$t('emails.spamFilterDialog.blacklisteAddressesPlaceholder')" rows="4"></textarea>
            <div class="error-label" v-if="spamFilterError.blocklist">{{ spamFilterError.blocklist }}</div>
          </FormGroup>

          <FormGroup>
            <label for="customConfigInput">{{ $t('emails.spamFilterDialog.customRules') }} <sup><a href="https://docs.cloudron.io/email/#custom-spam-filtering-rules" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
            <textarea id="customConfigInput" v-model="spamCustomConfig" :placeholder="$t('emails.spamFilterDialog.customRulesPlaceholder')" rows="4"></textarea>
            <div class="error-label" v-if="spamFilterError.config">{{ spamFilterError.config }}</div>
          </FormGroup>
        </fieldset>
      </form>
    </Dialog>

    <Section :title="$t('emails.settings.title')">
      <SettingsItem>
        <FormGroup>
          <label>{{ $t('emails.mailboxSharing.title') }}</label>
          <div>{{ $t('emails.mailboxSharing.description') }}</div>
        </FormGroup>
        <Switch v-model="mailboxSharingEnabled" @change="onChangeMailboxSharing"/>
        <SaveIndicator ref="mailboxSharingSaveIndicator"/>
      </SettingsItem>

      <SettingsItem>
        <FormGroup>
          <label>{{ $t('emails.settings.virtualAllMail') }}</label>
          <div v-html="$t('emails.changeVirtualAllMailDialog.description')"></div>
        </FormGroup>
        <Switch v-model="virtualAllMailEnabled" @change="onChangeVirtualAllMail"/>
        <SaveIndicator ref="virtualAllMailSaveIndicator"/>
      </SettingsItem>

      <SettingsItem wrap>
        <FormGroup>
          <label for="maxEmailSizeInput">{{ $t('emails.settings.maxMailSize') }}</label>
          <div v-html="$t('emails.changeMailSizeDialog.description')"></div>
        </FormGroup>
        <div style="display: flex; gap: 6px; align-items: center; flex-grow: 1; justify-content: end">
          {{ prettyDecimalSize(maxEmailSize) }}
          <input style="flex-grow: 1; max-width: 300px" type="range" id="maxEmailSizeInput" v-model="maxEmailSize" step="1000000" min="1000000" max="1000000000" :disabled="maxEmailSizeBusy" />
          <Button @click="onChangeMaxEmailSize()" tool :plain="currentMaxEmailSize !== maxEmailSize ? null : true" :loading="maxEmailSizeBusy" :disabled="maxEmailSizeBusy || currentMaxEmailSize === maxEmailSize">{{ $t('main.dialog.save') }}</Button>
        </div>
      </SettingsItem>

      <SettingsItem>
        <FormGroup>
          <label>{{ $t('emails.settings.solrFts') }}</label>
          <div v-html="$t('emails.solrConfig.description')"></div>
        </FormGroup>
        <Switch v-model="ftsEnabled" @change="onChangeFts" :disabled="!ftsEnabled && !hasMailServiceSufficientMemory"/>
        <SaveIndicator ref="ftsSaveIndicator"/>
      </SettingsItem>

      <SettingsItem>
        <FormGroup>
          <label>{{ $t('emails.settings.acl') }}</label>
          <div>{{ $t('emails.settings.aclOverview', { dnsblZonesCount }) }}</div>
        </FormGroup>
        <div style="display: flex; align-items: center">
          <Button tool plain @click="onShowAclDialog()">{{ $t('main.dialog.edit') }}</Button>
        </div>
      </SettingsItem>

      <SettingsItem>
        <FormGroup>
          <label>{{ $t('emails.settings.spamFilter') }}</label>
          <div>{{ $t('emails.settings.spamFilterOverview', { blacklistCount: blocklistCount }) }}</div>
        </FormGroup>
        <div style="display: flex; align-items: center">
          <Button tool plain @click="onShowSpamFilterDialog()">{{ $t('main.dialog.edit') }}</Button>
        </div>
      </SettingsItem>
    </Section>

    <MailServerLocation />
  </div>
</template>
