<i18n>
{
  "en": {
    "DictionaryEdit": {
      "title": "Edit dictionary",
      "createTitle": "Create dictionary",
      "viewTitle": "View title",
      "name": "Name",
      "code": "Code",
      "value": "Value",
      "documentsTitle": "Documents",
      "AddDocumentTitle": "New document",
      "AddDocumentEmptyError": "Fill in all the fields",
      "AddDocumentCoreError": "There is already an entry with this code",
      "jsonEditorMode": "Json editor mode",
      "formMode": "Form mode"
    }
  },
  "ru": {
    "DictionaryEdit": {
      "title": "Редактирование данных справочника",
      "createTitle": "Создание справочника",
      "viewTitle": "Просмотр справочника",
      "name": "Имя",
      "code": "Код",
      "value": "Значение",
      "documentsTitle": "Записи",
      "AddDocumentTitle": "Новая запись",
      "AddDocumentEmptyError": "Заполните все поля",
      "AddDocumentCoreError": "Запись с таким кодом уже есть",
      "jsonEditorMode": "Режим редактора json",
      "formMode": "Режим формы"
    }
  }
}
</i18n>

<template>
  <q-dialog v-model="dialogOpen" @hide="clearModel">
    <q-card class="full-width no-shadow" style="max-width: 800px">
      <q-card-section>
        <div class="text-h6">
          {{
            isEditForm
              ? $t('DictionaryEdit.title')
              : isReadOnlyForm
              ? $t('DictionaryEdit.viewTitle')
              : $t('DictionaryEdit.createTitle')
          }}
        </div>
      </q-card-section>
      <q-card-section class="q-pb-md q-gutter-y-md">
        <q-btn-toggle
          v-if="isEditForm"
          v-model="jsoneditorMode"
          toggle-color="primary"
          :options="toggleBtnOptions"
        />
        <v-json-editor
          v-if="jsoneditorMode"
          ref="jsoneditor"
          v-model="dialogData"
          :options="{ mode: 'code' }"
          height="400px"
        />
        <div
          v-if="dialogData && (dialogData.id || !isEditForm) && !jsoneditorMode"
          class="q-gutter-y-md"
        >
          <q-input
            v-model="dialogData.id"
            filled
            :readonly="isEditForm || isReadOnlyForm"
            :label="$t('DictionaryEdit.code')"
          />

          <q-input
            v-model="dialogData.name"
            filled
            :label="$t('DictionaryEdit.name')"
            :readonly="isReadOnlyForm"
          />

          <div class="text-h6">{{ $t('DictionaryEdit.documentsTitle') }}</div>
          <div v-if="dialogData.documents" class="q-gutter-sm">
            <div
              v-for="(item, index) in dialogData.documents"
              :key="`document-${index}`"
              class="row q-gutter-sm"
            >
              <div class="col">
                <q-input
                  v-model="item.code"
                  filled
                  :readonly="isReadOnlyForm"
                  :label="$t('DictionaryEdit.code')"
                >
                  <template #before>
                    <q-btn
                      v-if="!isReadOnlyForm"
                      text-color="primary"
                      dense
                      icon="delete"
                      flat
                      @click="deleteDocument(item)"
                    />
                  </template>
                </q-input>
              </div>

              <div class="col">
                <q-input
                  v-model="item.value"
                  filled
                  :readonly="isReadOnlyForm"
                  :label="$t('DictionaryEdit.value')"
                />
              </div>
              <div v-if="dialogData.userMeta && item" class="row q-gutter-x-sm">
                <div
                  v-for="(userMetaItem, i) in dialogData.userMeta"
                  :key="`metaItem-${i}`"
                  class="col"
                >
                  <q-input
                    v-if="!userMetaItem.isDraft"
                    v-model="item[userMetaItem.code]"
                    filled
                    :readonly="isReadOnlyForm"
                    :label="userMetaItem.name"
                  />
                </div>
              </div>
            </div>
          </div>
          <q-btn
            v-if="!addDocuments && !isReadOnlyForm"
            color="white"
            text-color="primary"
            outline
            @click="addDocuments = true"
          >
            Добавить запись
          </q-btn>
          <div
            v-if="addDocuments && newDocumentsModel && !isReadOnlyForm"
            class="q-gutter-sm"
          >
            <div class="text-h6">
              {{ $t('DictionaryEdit.AddDocumentTitle') }}
            </div>

            <q-input
              v-model="newDocumentsModel.code"
              filled
              :label="$t('DictionaryEdit.code')"
            />

            <q-input
              v-model="newDocumentsModel.value"
              filled
              :label="$t('DictionaryEdit.value')"
            />
            <div v-if="dialogData.userMeta">
              <div
                v-for="(item, i) in dialogData.userMeta"
                :key="`metaItem-${i}`"
                class="q-gutter-y-sm q-mt-sm"
              >
                <q-input
                  v-if="!item.isDraft"
                  v-model="newDocumentsModel[item.code]"
                  filled
                  :label="item.name"
                />
              </div>
            </div>
            <q-btn unelevated color="primary" @click="addNewDocument">
              Добавить</q-btn
            >
          </div>
          <q-list v-if="!isReadOnlyForm" class="bg-grey-2">
            <q-expansion-item>
              <template #header>
                <q-item-section>
                  <b>Дополнительные поля</b>
                </q-item-section>
              </template>
              <q-card class="bg-grey-2">
                <q-card-section v-if="userMeta.length" class="q-gutter-y-md">
                  <div v-for="(item, i) in userMeta" :key="`item-${i}`">
                    <div class="row q-gutter-sm">
                      <q-input
                        v-model="item.code"
                        filled
                        class="col"
                        label="Kод поля"
                        bg-color="white"
                      >
                        <template #before>
                          <q-btn
                            v-if="item.isDraft"
                            dense
                            color="grey-2"
                            text-color="primary"
                            icon="check"
                            class="q-ml-auto"
                            @click="addUserMetaField(item)"
                          />
                          <q-btn
                            v-else
                            dense
                            color="grey-2"
                            text-color="primary"
                            icon="delete"
                            class="q-ml-auto"
                            @click="deleteUserMetaField(item)"
                          />
                        </template>
                      </q-input>
                      <q-input
                        v-model="item.name"
                        filled
                        class="col"
                        label="Имя поля"
                        bg-color="white"
                      />
                    </div>
                  </div>
                </q-card-section>
                <q-card-actions align="right">
                  <q-btn
                    color="primary"
                    label="Добавить запись"
                    @click="addEmptyUserMetaField()"
                  />
                </q-card-actions>
              </q-card>
            </q-expansion-item>
          </q-list>
        </div>
      </q-card-section>
      <q-card-actions align="right">
        <q-btn
          v-if="isEditForm && !isReadOnlyForm"
          label="Cохранить"
          unelevated
          color="primary"
          @click="edit"
        />
        <q-btn
          v-else-if="!isReadOnlyForm"
          label="Создать"
          unelevated
          color="primary"
          @click="create"
        />

        <q-btn
          label="Закрыть"
          color="white"
          text-color="primary"
          outline
          @click="dialogOpen = false"
        />
      </q-card-actions>
    </q-card>
  </q-dialog>
</template>
<script lang="ts">
// @ts-nocheck
// @ts-ignore
import VJsonEditor from 'v-jsoneditor';
import { DictionaryApi } from '@openapi/registry-service';
import cloneDeep from 'lodash/cloneDeep';
import get from 'lodash/get';
import { notifyError } from '@utils/notify';

const dictionaryApi = new DictionaryApi();
export default {
  components: {
    VJsonEditor,
  },
  props: ['common', 'model'],
  data() {
    return {
      dialogData: null,

      editOnly: false,

      mode: 'edit',

      newDocumentsModel: null,

      emptyField: {
        code: '',
        name: '',
        isDraft: true,
      },

      defaultDictionaryModel: {
        id: '',
        name: '',
      },

      defaultDocumentsModel: {
        code: '',
        value: '',
      },

      userMeta: [],

      schemaName: 'Dictionary',

      addDocuments: false,

      dialogOpen: false,

      jsoneditorMode: false,

      toggleBtnOptions: [
        {
          label: this.$t('DictionaryEdit.jsonEditorMode'),
          value: true,
        },
        {
          label: this.$t('DictionaryEdit.formMode'),
          value: false,
        },
      ],
    };
  },

  computed: {
    isEditForm() {
      return this.mode === 'edit';
    },
    isReadOnlyForm() {
      return this.mode === 'view';
    },
  },

  watch: {
    'common.models.DictionaryDialog': {
      immediate: true,
      handler: function (val) {
        if (val) {
          this.dialogOpen = true;
          this.mode = val.mode || 'edit';
          if (this.mode === 'create') {
            if (!val.data) {
              this.dialogData = cloneDeep(this.defaultDictionaryModel);
            } else {
              this.dialogData = val.data;
              this.userMeta = val?.data?.userMeta || [];
            }
            return;
          }
          this.dialogData = val.data;
          if (val?.data?.userMeta) {
            this.userMeta = val.data.userMeta.map((i) => {
              i.isDraft = false;
              return i;
            });
          }
          this.editOnly = val.editOnly;
        }
      },
    },
  },

  mounted() {
    this.newDocumentsModel = cloneDeep(this.defaultDocumentsModel);
  },

  destroyed() {
    this.clearModel();
  },

  methods: {
    deleteUserMetaField(item) {
      if (!item.code || !item.name) {
        notifyError(this.$t('DictionaryEdit.AddDocumentEmptyError'));
        return;
      }

      this.userMeta = this.userMeta.filter((i) => i.code !== item.code);

      if (get(this.dialogData, 'userMeta')) {
        this.dialogData.userMeta = this.dialogData.userMeta.filter(
          (i) => i.code !== item.code
        );
      }

      if (get(this.dialogData, 'documents')) {
        this.dialogData.documents.forEach((el) => {
          delete el[item];
        });
      }
    },
    addNewDocument() {
      if (
        !this.dialogData ||
        !this.newDocumentsModel ||
        (!this.newDocumentsModel.code && !this.newDocumentsModel.value)
      ) {
        notifyError(this.$t('DictionaryEdit.AddDocumentEmptyError'));

        return;
      }

      if (
        this.dialogData.documents &&
        this.dialogData.documents.some(
          (i) => i.code === this.newDocumentsModel.code
        )
      ) {
        notifyError(this.$t('DictionaryEdit.AddDocumentCoreError'));

        return;
      }

      const documents = this.dialogData.documents || [];

      documents.push(this.newDocumentsModel);

      this.dialogData.documents = documents;
      this.newDocumentsModel = cloneDeep(this.defaultDocumentsModel);
      this.addDocuments = false;
    },

    addUserMetaField(item) {
      if (!item.code || !item.name || !this.dialogData) {
        notifyError(this.$t('DictionaryEdit.AddDocumentEmptyError'));
        return;
      }
      item.isDraft = false;
      if (!this.dialogData.userMeta) {
        this.dialogData.userMeta = [];
      }
      this.dialogData.userMeta.push({
        name: item.name,
        code: item.code,
      });
      this.$nextTick(() => this.$forceUpdate());
    },

    deleteDocument(document) {
      if (!this.dialogData || !this.dialogData.documents) {
        return;
      }
      this.dialogData.documents = this.dialogData.documents.filter((i) => {
        return i.code !== document.code;
      });
    },

    async edit() {
      if (!get(this.dialogData, 'id')) {
        notifyError(this.$t('DictionaryEdit.AddDocumentCoreError'));
        return;
      }

      try {
        const { data: result } = await dictionaryApi.updateDictionary([
          this.dialogData,
        ]);

        this.dialogData.id = result.objectIds[0];
        this.dialogData.modified = result.modified;

        if (!this.editOnly) {
          const card = cloneDeep(
            this.$store.getters['registryService/services/servicesCard']
          );

          const dictionaries = card.dictionaries.map((it) =>
            it.id === this.dialogData.id ? this.dialogData : it
          );

          card.dictionaries = dictionaries;

          this.$store.dispatch('registryService/services/setCardForJson', card);
        }
      } catch (e) {
        notifyError(e.message.toString());
      } finally {
        this.dialogOpen = false;
      }
    },

    async create() {
      if (!this.dialogData || !this.dialogData.id) {
        notifyError(this.$t('DictionaryEdit.AddDocumentCoreError'));
        return;
      }
      try {
        const { data: result } = await dictionaryApi.createDictionary([
          this.dialogData,
        ]);

        this.dialogData.id = result.objectIds[0];

        const card = cloneDeep(
          this.$store.getters['registryService/services/servicesCard']
        );

        const dictionaries = card.dictionaries || [];

        dictionaries.push(this.dialogData);

        card.dictionaries = dictionaries;

        this.$store.dispatch('registryService/services/setCardForJson', card);
      } catch (e) {
        notifyError(e.message.toString());
      } finally {
        this.dialogOpen = false;
      }
    },
    addEmptyUserMetaField() {
      if (!this.dialogData) return;

      this.userMeta.push(cloneDeep(this.emptyField));

      this.$nextTick(() => this.$forceUpdate());
    },
    clearModel() {
      this.dialogData = cloneDeep(this.defaultDictionaryModel);
      this.newDocumentsModel = cloneDeep(this.defaultDocumentsModel);
      this.jsoneditorMode = false;
      this.$emit('commonModels', {
        DictionaryDialog: null,
      });
    },
  },
};
</script>
