import { Component, Vue, Watch } from 'vue-property-decorator';
import get from 'lodash/get';
import merge from 'lodash/merge';
import { Route } from 'vue-router';
import { BaseCardCommonModels, BaseCardCommon } from '@/interfaces';
import { sha256 } from 'js-sha256';
import { WorkflowServiceApi } from '@openapi/wf';
import { notifyError } from '@utils/notify';

const wfApi = new WorkflowServiceApi();

Component.registerHooks(['beforeRouteLeave']);

@Component({})
export default class BaseCard extends Vue {
  private unsavedChanges = false;

  // хак для перерендеринга карточки
  private reloadKey = 0;

  private mounted(): void {
    this.$root.$on('unsavedChanges', (unsavedChanges: boolean) => {
      this.unsavedChanges = unsavedChanges;
    });
  }

  beforeRouteLeave(to: Route, from: Route, next: any) {
    if (
      this.unsavedChanges &&
      !window.confirm('На странице есть несохраненные изменения. Продолжить?')
    ) {
      next(false);
    } else {
      next();
    }
  }

  @Watch('hash', {
    immediate: true,
  })
  private hashHandler(): void {
    this.init();
  }

  private get active(): string | undefined {
    return get(this.$route, 'query.active');
  }

  private get common(): BaseCardCommon {
    return {
      $websockets: this.$websockets,
      active: this.active,
      id: this.id,
      models: this.commonModels,
      needToUpdate: this.needToUpdate,
      path: this.path,
    };
  }

  get components(): string[] {
    return get(this.$route, 'query.components', '').split(',');
  }

  get userTasks() {
    return this.$store.getters['utils/cards/userTasks'];
  }

  get models() {
    return this.$store.getters['utils/cards/models'];
  }

  get needToUpdate() {
    return this.$store.getters['utils/cards/needToUpdate'];
  }

  private get id(): string | undefined {
    return get(this.$route, 'params.id');
  }

  private get hash(): string {
    return sha256(`${this.path}/${this.id}`).toString();
  }

  private get path(): string | undefined {
    return get(this.$route, 'params.path');
  }

  private loading = true;

  comps: string[] = [];

  private commonModels: BaseCardCommonModels = {}; // TODO check usage?

  private async init(): Promise<void> {
    this.loading = true;

    await this.initCommonModels();

    this.initCards();
    this.loading = false;
  }

  private initCommonModels() {
    this.components.forEach((component) => {
      this.commonModels[component] = {};
    });
  }

  private initCards() {
    this.comps = this.components.map((component) =>
      this.$GlobalComponentImporter.registerComponent(
        component,
        `cards/${this.path}/`
      )
    );
  }

  private commonModelsHandler(val: BaseCardCommonModels): void {
    this.commonModels = merge({}, this.commonModels, val);
  }

  private submit({
    requestBody,
    taskId,
    cb,
  }: {
    requestBody: any;
    taskId: string;
    cb: any;
  }): void {
    wfApi
      .submitForm(taskId, requestBody)
      .then(() => {
        if (cb) cb();
      })
      .catch((e) => {
        notifyError(e.message.toString());
      })
      .finally(() => {
        this.$store.dispatch('commonComponents/baseChecksTable/setLoading', false);
      });
  }
}
