<template v-if="version">
  <loader>
    <div class="row">
      <div class="column" :class="isNew ? 'col-12' : 'col-9'">
        <ul class="nav nav-tabs">
          <li
            v-for="section in schemaSections"
            class="nav-item"
            :class="!isSchemaSectionValid(section.key) && 'text-danger'"
            v-bind:key="section.key"
          >
            <a
              class="nav-link"
              :class="{
                active: isActiveSection(section.key),
                invalid: !isActiveSection(section.key) && !isSchemaSectionValid(section.key)
              }"
              v-on:click="setActiveSection(section.key)"
            >
              {{ section.key }}
              <span v-if="!isSchemaSectionValid(section.key)" class="icon-notification ml-1"></span>
            </a>
          </li>
        </ul>

        <div
          class="schema-editor"
          v-for="section in schemaSections"
          v-bind:key="section.key"
          :class="{ active: isActiveSection(section.key) }"
        >
          <main class="card">
            <div class="card-body">
              <validator-group :ref="schemaSectionRefName(section.key)">
                <editor v-if="section.key !== 'Scheduling'" :item="version" :schema="section.schema"></editor>
                <div v-else-if="!isReadOnly">
                  <field label="Schedule start">
                    <datetime-picker
                      v-model="version.publishDate"
                      :schema="versionSchemaProperties.publishDate"
                      :max="version.depublishDate"
                      :readonly="hasRecurringSchedules"
                    ></datetime-picker>
                  </field>

                  <field label="Schedule stop">
                    <datetime-picker
                      v-model="version.depublishDate"
                      :schema="versionSchemaProperties.depublishDate"
                      :min="version.publishDate"
                      :readonly="hasRecurringSchedules"
                    ></datetime-picker>
                    <validator :test="!version.publishDate || !version.depublishDate || version.publishDate < version.depublishDate">
                      Schedule start ligt na schedule stop
                    </validator>
                  </field>

                  <div v-show="hasRecurringSchedules" class="footnote offset-sm-4 col-sm-8">
                    Bij terugkerende schedules worden de start/stop velden automatisch gevuld op basis van de ingestelde schedules.
                  </div>

                  <field label="Terugkerende schedule(s)" v-if="!isNew">
                    <recurring-schedule-input
                      :version="version"
                      :recurrent-schedules.sync="recurringSchedules"
                      :permissions="permissions"
                    ></recurring-schedule-input>
                  </field>
                </div>
              </validator-group>
            </div>
          </main>
        </div>
      </div>
      <div v-if="!isNew && !isReadOnly" class="column col-3">
        <version-actions
          :version="version"
          :dialog="dialog"
          :schema="schema"
          :changed="changed"
          :resetChanged="resetChanged"
          :hasRecurringSchedules="hasRecurringSchedules"
          :allPublished="allPublished"
          :versionIsPublished="versionIsPublished"
          :versionIsLive="versionIsLive"
          :page="page"
          :previewUrl="previewUrl"
          @cancelChanges="cancelChanges"
        >
        </version-actions>
      </div>
    </div>

    <validator v-if="!isNew" :test="changed"></validator>
  </loader>
</template>

<style lang="scss" scoped>
.meta {
  background: linear-gradient(to bottom, #fff 60%, rgba(255, 255, 255, 0) 100%);
  border-left: 1px solid #ddd;
  border-right: 1px solid #ddd;
}

.card {
  border-top: none;
}

.nav.nav-tabs .nav-link {
  cursor: pointer;

  &.invalid {
    color: inherit;
  }
}

.schema-editor {
  position: absolute;
  top: -10000px;
  left: -10000px;
}

.schema-editor.active {
  position: static;
}

.version-actions {
  display: flex;

  .right {
    margin-left: auto;
  }
}

.footnote {
  color: #55595c;
  font-size: 14px;
  margin-bottom: 1.3rem;
}

.references {
  display: inline-block;
}
</style>

<script lang="ts">
import _ from 'lodash';
import { Component, Prop, Ref, Vue, Watch } from 'vue-property-decorator';
import { namespace } from 'vuex-class';
import PageApi from '../api/page-api';
import editor from '../shared/editor.vue';
import formElements from '../shared/form/all';
import recurringScheduleInput from '../shared/form/recurring-schedule-input.vue';
import loader from '../shared/loader.vue';
import references from '../shared/references.vue';
import { SchemaItem, Version, VersionedPage } from '../types/api';
import { PageEditorState } from './page-editor.vue';
import VersionActions from './version-actions.vue';
import ConfirmDialog from '../shared/form/confirm-dialog.vue';

const PagesStore = namespace('pages');

@Component({
  components: {
    VersionActions,
    editor,
    loader,
    recurringScheduleInput,
    references,
    ...formElements
  }
})
export default class VersionEditor extends Vue {
  @Prop() readonly allPublished!: Version[];
  @Prop() readonly dialog!: ConfirmDialog | undefined;
  @Prop() readonly page!: VersionedPage | null;
  @Prop() readonly versionIsPublished!: boolean;

  @Prop(Object) version!: Version;
  @Prop(Object) state!: PageEditorState;
  @Prop(Object) permissions!: object; // TODO fix type
  @Prop(Boolean) isNew!: boolean;
  @Prop(Boolean) isReadOnly!: boolean;
  @Ref('refsDialog') readonly refsDialog!: typeof references;
  @PagesStore.Getter('types') readonly types!: { [key: string]: SchemaItem };

  changed = false;
  preview = false;
  versionCounter = 0;
  activeSection = 'Content';
  recurringSchedules: object[] = []; // TODO fix propper type

  @Watch('version', { deep: true })
  versionUpdateHandler(newValue: Version, oldValue: Version) {
    // the whole version can change as well, only set 'changed' prop when editing on the same version
    if (newValue.id == oldValue.id) {
      this.changed = true;
    } else {
      this.resetChanged();
    }
  }

  setActiveSection(key: string) {
    this.activeSection = key;
  }

  resetChanged() {
    // There might be pending changes to this.version, wait those out.
    this.$nextTick(() => {
      this.changed = false;
      this.versionCounter++;
    });
  }

  openReferencesErrorModal() {
    this.refsDialog.openErrorModal();
  }

  cancelChanges() {
    this.$emit('cancelChanges');
  }

  get previewUrl(): string | null {
    // Updating the versionCounter is will trigger a refresh of the preview iframes
    return PageApi.previewUrl(this.version, this.versionCounter);
  }

  get stateClass() {
    return this.version == this.state.live ? 'btn-success' : this.state.published ? 'btn-warning' : 'disabled';
  }

  get versionSchemaProperties() {
    return this.$store.state.pages.schema.properties;
  }
  get isLoading() {
    return !this.schema;
  }
  get schema() {
    return this.types[this.version.$type];
  }
  get hasRecurringSchedules() {
    return this.recurringSchedules.length > 0;
  }
  get schemaSections() {
    if (!this.schema) {
      return;
    }
    const defaultSchemaSection = 'Content';

    const properties = _.mapValues(
      {
        ...this.versionSchemaProperties,
        ..._.omit(this.schema.properties, '$type')
      },
      (v) => ({
        ...v,
        schemaSection: v.metadataSection || defaultSchemaSection
      })
    );

    const groupedSchemas = _.chain(properties)
      .toPairs()
      .groupBy((p) => p[1].schemaSection)
      .mapValues((g) => _.fromPairs(g))
      .map((value, key) => ({
        key,
        schema: { ...this.schema, properties: value }
      }))
      .value();
    const contentSection = _.remove(groupedSchemas, (s) => s.key == defaultSchemaSection);

    return [contentSection[0], ...groupedSchemas];
  }

  get versionIsLive() {
    return this.version == this.state.live;
  }

  isActiveSection(key: string) {
    return key == this.activeSection;
  }

  schemaSectionRefName(key: string) {
    return `schema-section-validator-${key}`;
  }

  isSchemaSectionValid(key: string) {
    const refList = this.$refs[this.schemaSectionRefName(key)] as any;
    const ref = refList && refList[0];
    return ref ? ref.isValid : true;
  }

  get hasChanged() {
    return this.changed;
  }
}
</script>
