<template>
  <loader class="h-100" :is-loading="isLoading">
    <portal to="top-header-title" v-if="page">
      {{ isFolder ? 'Folder' : 'Pagina' }} aanmaken
    </portal>
    <page-bread-crumbs class="mb-3" v-if="page.parentId" :page="page" />
    <p class="mb-3 text-secondary" v-else>/ {{ page.name }}</p>
    <validator-group :class="{ 'h-100': isCreatingNewPage }" v-if="initialized">
      <section class="h-100 d-flex flex-column">
        <page-editor-structure :page="page" :with-actions="false" />
        <field label="Pagina type">
          <select class="form-control" :value="pageTypeId" @change="changePageTypeId($event.target.value)">
            <option value="">Kies paginatype</option>
            <option v-for="(type, key) in orderedTypes" :key="key" :value="getPageTypeId(type)" v-if="!type.isSingleton && !type.preventCreate">{{ type.title }}</option>
            <option value="" disabled>-------------</option>
            <option v-for="(type, key) in orderedTypes" :key="key" :value="getPageTypeId(type)" v-if="type.isSingleton && !type.preventCreate">{{ type.title }}</option>
          </select>
        </field>
        <validator :test="!!pageTypeId"></validator>
        <div v-if="isFolder">
          <submit class="align-self-start" :action="create">Folder aanmaken</submit>
        </div>
        <page-version-editor ref="versionEditor" :version="pageVersion" :page="page" :permissions="permissions" v-if="isCreatingNewPage" @validate="(valid) => isValid = valid" is-new>
          <template v-slot:sidebar>
            <div class="px-3 mb-2">
              <submit class="btn-block" :action="create">Opslaan</submit>
            </div>
            <div class="px-3">
              <div class="alert alert-warning" v-if="!isValid">
                Er zijn verplichte velden die nog niet zijn ingevuld. Vul deze in om de pagina aan te maken.
              </div>
            </div>
          </template>
        </page-version-editor>
        <confirm-dialog ref="dialog"></confirm-dialog>
      </section>
    </validator-group>
  </loader>
</template>

<script lang="ts">
import { Vue, Component, Ref, Watch } from 'vue-property-decorator';
import _orderBy from 'lodash/orderBy';
import { namespace } from 'vuex-class';

// @ts-ignore
import * as formElements from '../shared/form/all.js';
import PageEditorStructure from './page-editor-structure.vue';
import PageVersionEditor from './page-version-editor.vue';
import Loader from '../shared/loader.vue';
import NewPageNav from './new-page-nav.vue';
import CopyPagePicker from './copy-page-picker.vue';
import PageBreadCrumbs from './page-bread-crumbs.vue';

// @ts-ignore
import { initialValue } from '../schema/schema-scripts.js';
import { Page, Version } from '../types/api';
import { PageEditorPermissions } from './page-editor.vue';
import { PermissionListModel } from '../stores/types/PermissionStoreModel';
import { Route } from 'vue-router';
import { RawLocation } from 'vue-router/types/router';
import Validator from '../shared/form/validator.vue';
import RouteUtils, { createRoute, ROUTES } from '../tools/route-utils';

const PermissionStore = namespace('permissions');
const PageStore = namespace('pages');
const AlertStore = namespace('alerts');

const DEFAULT_PAGE_NAME = 'nieuwe-pagina';
const DEFAULT_FOLDER_NAME = 'nieuwe-folder';
const FOLDER_TYPE_ID = 'Q42.Cms.Core.Domain.Folder, Q42.Cms.Core.Domain';
const VIRTUALPAGE_TYPE_ID = 'Q42.Cms.Core.Domain.VirtualPage, Q42.Cms.Core.Domain';

@Component({
  components: {
    Validator,
    PageVersionEditor,
    NewPageNav,
    PageEditorStructure,
    PageBreadCrumbs,
    Loader,
    CopyPagePicker,
    ...formElements
  },
  beforeRouteEnter(to: Route, from: Route, next: (to?: RawLocation | false | ((vm: NewPageEditor) => any) | void) => void) {
    next(vm => {
      vm.isLoading = false;
    });
  },
  beforeRouteLeave(to: Route, from: Route, next: (to?: RawLocation | false | ((vm: NewPageEditor) => any) | void) => void) {
    if ((this as any).$refs.versionEditor && (this as any).$refs.versionEditor.changed) {
      (this as any).$refs.dialog.confirm(
        'De nieuwe pagina is nog niet opgeslagen',
        'Wil je de nieuwe pagina verwijderen?'
      ).then((isConfirmed: any) => {
        next(isConfirmed);
      });
    } else {
      next();
    }
  },
})
export default class NewPageEditor extends Vue {
  @Ref() readonly dialog!: any;
  @Ref() readonly versionEditor!: PageVersionEditor;

  pageTypeId = '';
  pageVersion: Partial<Version> | null = null;
  pageVersionId: string | null = null;
  isLoading = true;
  isValid = false;
  page: Partial<Page> = {
    name: DEFAULT_PAGE_NAME,
    parentId: null,
  }

  @PermissionStore.Getter('getPermissions') readonly getPermissions!: (itemName: string) => PermissionListModel;
  @PageStore.State('initialized') readonly initialized!: boolean;
  @PageStore.Getter('types') readonly types!: any;
  @AlertStore.Action('addError') readonly addError!: (message: string) => void;

  beforeMount() {
    if (this.initialized) {
      this.setup();
    }
  }

  setup() {
    const { parentId } = this.$route.params;
    const { isFolder } = this.$route.query;

    if (parentId) {
      this.page.parentId = parentId;
    }

    if (isFolder) {
      this.pageTypeId = FOLDER_TYPE_ID;
      this.page.name = DEFAULT_FOLDER_NAME;
      this.changePageTypeId(FOLDER_TYPE_ID);
    }
  }

  getPageTypeId(type: any) {
    return type.properties.$type.enum[0];
  }

  async changePageTypeId(pageTypeId: string) {
    if (pageTypeId === '') {
      this.pageTypeId = pageTypeId;
      this.pageVersion = null;
    } else {
      const selectedPageType = this.types[pageTypeId];
      const { name } = this.page;

      this.initializePageVersion(pageTypeId, initialValue(selectedPageType));

      if (name === DEFAULT_FOLDER_NAME || name === DEFAULT_PAGE_NAME) {
        this.page.name = pageTypeId === FOLDER_TYPE_ID ? DEFAULT_FOLDER_NAME : DEFAULT_PAGE_NAME;
      }
    }
  }

  initializePageVersion(pageTypeId: string, version: Partial<Version>) {
    this.pageTypeId = pageTypeId;
    this.pageVersion = {
      $type: pageTypeId, // NB: API needs $type to be first!
      publishDate: this.pageVersion && this.pageVersion.publishDate,
      depublishDate: this.pageVersion && this.pageVersion.depublishDate,
      metaIndex: this.pageVersion ? this.pageVersion.metaIndex : true,
      showPostFix: this.pageVersion ? this.pageVersion.showPostFix : true,
      metaFollow: this.pageVersion ? this.pageVersion.metaFollow : true,
      ...version
    };
  }

  async create() {
    try {
      const { name, parentId } = this.page;
      const pageVersion = await this.$store.dispatch('pages/create', { version: this.pageVersion, name, parentId });

      if (this.versionEditor) {
        this.versionEditor.changed = false;
        await RouteUtils.push(createRoute(ROUTES.PAGE_EDITOR_VERSION, { id: pageVersion.pageId, versionId: pageVersion.id }));
      } else {
        await RouteUtils.push(createRoute(ROUTES.PAGE_EDITOR, { id: pageVersion.page.id }));
      }
    } catch (e) {
      console.error(e.message);
      const errorMessage = e.message.split(':')[1];
      await this.addError(`Pagina aanmaken is niet gelukt! <br> ${errorMessage}`);
    }
  }

  get permissions(): PageEditorPermissions {
    return {
      ...this.getPermissions('CmsPage'),
      canDepublish: false
    };
  }

  get isFolder(): boolean {
    return this.pageTypeId === FOLDER_TYPE_ID;
  }

  get isVirtualPage(): boolean {
    return this.pageTypeId === VIRTUALPAGE_TYPE_ID;
  }

  get orderedTypes() {
    return _orderBy(this.types, 'title');
  }

  get isCreatingNewPage(): boolean {
    return !!(this.pageVersion && !this.isFolder);
  }

  @Watch('initialized')
  onInitializedChange() {
    this.setup();
  }
}
</script>
