<template>
  <loader>
    <header class="page-header pt-4 pb-3">
      <h1>{{ capitalizeModuleName }} Overzicht</h1>

      <span class="page-header-buttons" v-if="canCreate">
        <router-link class="btn btn-primary" :to="createItemRoute">
          <span class="icon-plus"></span> {{ capitalizeModuleName }} toevoegen
        </router-link>
      </span>
    </header>

    <item-list
      :items="searchResultItems"
      :fields="fields"
      :schema="schema"
      :action="openItem"
      :custom-fields="customFields"
      :module="module"
      :is-loading="isLoadingListItems"
    ></item-list>
  </loader>
</template>

<script lang="ts">
import { namespace } from 'vuex-class';

import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
import CrudStoreModel, { BaseSchemaModel, CrudStoreItemsModel, CrudStoreSchemaModel } from '../stores/types/CrudStoreModel';

import Loader from '../shared/loader.vue';
import Listing from '../shared/listing.vue';

const PermissionStore = namespace('permissions');

@Component({
  components: {
    Loader,
    'item-list': Listing
  }
})
export default class CrudOverview<T extends CrudStoreModel> extends Vue {
  @Prop(String) readonly module!: string;
  @Prop(Object) readonly crudStore!: T;

  @PermissionStore.Getter('canCreate') readonly canCreatePermission!: Function;

  isLoadingListItems = false;
  isLoadingListItemsTimeout: ReturnType<typeof setTimeout> | undefined = undefined;

  openItem(item: CrudStoreItemsModel) {
    this.$router.push({
      name: `${this.module}-editor`,
      params: {
        id: item.id as string
      },
      query: this.$route.query
    });
  }

  get createItemRoute() {
    return {
      name: `create-${this.module}`,
      query: this.$route.query
    };
  }

  get searchResultItems(): CrudStoreItemsModel[] {
    return this.crudStore.latestSearchResult ? this.crudStore.latestSearchResult.items : [];
  }

  get schema(): CrudStoreSchemaModel | undefined {
    return this.crudStore.schema;
  }

  get fields(): object {
    const fields: {
      [k: string]: string;
    } = {};

    if (this.crudStore.overview.fields) {
      this.crudStore.overview.fields.forEach((property) => {
        if (!this.crudStore.schema) {
          return;
        }

        const schemaForProperty = this.crudStore.schema.properties[property];
        if (!schemaForProperty) {
          return;
        }

        fields[(schemaForProperty as BaseSchemaModel).title] = property;
      });
    }

    if (this.crudStore.overview.additionalFields) {
      Object.assign(fields, this.crudStore.overview.additionalFields);
    }

    return fields;
  }

  get customFields(): object | undefined {
    if (!this.crudStore.overview) {
      return undefined;
    }

    return this.crudStore.overview.customFields;
  }

  get isLoading(): boolean {
    return !this.crudStore.schema || !this.crudStore.overview;
  }

  get capitalizeModuleName(): string {
    if (!this.crudStore.schema) {
      return '';
    }

    return this.crudStore.schema.title;
  }

  get canCreate(): boolean {
    if (!this.crudStore.schema) {
      return false;
    }

    return !this.crudStore.schema.preventCreate && this.canCreatePermission(this.module);
  }

  @Watch('crudStore.loading')
  onIsLoadingChanged(isLoading: boolean) {
    if (isLoading) {
      // If the request is super fast, we don't want to show the loader.
      // We wait 100ms before showing the loader.
      this.isLoadingListItemsTimeout = setTimeout(() => {
        this.isLoadingListItems = true;
      }, 100);
    } else {
      clearTimeout(this.isLoadingListItemsTimeout);
      this.isLoadingListItemsTimeout = undefined;
      this.isLoadingListItems = false;
    }
  }
}
</script>
