<script setup>
import { computed, ref, watch, watchEffect } from "vue";
import { cloneDeep, isEqual } from "lodash-es";
const props = defineProps({
  fullscreen: { type: Boolean, required: false },
  title: { type: String, required: false },
  initialData: { type: Object, required: false },
  formData: { type: Object, required: false },
  saveCaption: { type: String, required: false, default: "\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01" },
  cancelCaption: { type: String, required: false, default: "\u0E22\u0E01\u0E40\u0E25\u0E34\u0E01" },
  closeCaption: { type: String, required: false, default: "\u0E1B\u0E34\u0E14" },
  saveAndStay: { type: Boolean, required: false, default: false },
  readonly: { type: Boolean, required: false, default: false }
});
const isShowing = defineModel({ type: Boolean, ...{ default: false } });
const isSaving = ref(false);
const isSavedAndStay = ref(false);
const formPadRef = ref();
const formData = ref({});
const formDataOriginalValue = ref();
const emit = defineEmits(["create", "update"]);
function save() {
  formPadRef.value?.flushSanitize?.();
  if (formPadRef.value.isValid) {
    isSaving.value = true;
    emit(isCreating.value ? "create" : "update", cloneDeep(formData.value), props.saveAndStay ? stayCallback : callback);
  }
}
function cancel() {
  isShowing.value = false;
}
const callback = {
  done: function() {
    isSaving.value = false;
    isShowing.value = false;
  },
  error: function() {
    isSaving.value = false;
  }
};
const stayCallback = {
  done: function() {
    isSaving.value = false;
    isSavedAndStay.value = true;
  },
  error: function() {
    isSaving.value = false;
  },
  setData: function(item) {
    formData.value = cloneDeep(item);
    formDataOriginalValue.value = cloneDeep(item);
  }
};
const isDataChange = computed(() => {
  return !(isCreating.value ? isEqual(formData.value, createOriginalValue.value) : isEqual(formData.value, formDataOriginalValue.value));
});
const isCreating = computed(() => {
  return !props.formData && !isSavedAndStay.value;
});
const createOriginalValue = computed(() => {
  return Object.assign({}, props.initialData);
});
const loadFormData = () => {
  if (props.formData) {
    formData.value = cloneDeep(props.formData);
    formDataOriginalValue.value = cloneDeep(props.formData);
  } else {
    formData.value = Object.assign({}, cloneDeep(props.initialData));
  }
  isSavedAndStay.value = false;
};
const operation = ref({ isDataChange, isCreating, isSaving, save, cancel });
watchEffect(loadFormData);
watch(() => isShowing.value, (newValue) => {
  if (newValue) loadFormData();
});
</script>

<template>
  <v-dialog
    v-model="isShowing"
    :fullscreen="fullscreen"
    persistent
    scrollable
  >
    <VCard>
      <VToolbar>
        <VToolbarTitle>
          <slot name="title" :operation="operation">
            {{ isCreating ? "New" : "Edit" }} {{ title }}
          </slot>
        </VToolbarTitle>
        <VSpacer />
        <VToolbarItems>
          <VBtn
            icon="mdi mdi-close"
            @click="cancel"
          />
        </VToolbarItems>
      </VToolbar>
      <VCardText>
        <form-pad
          ref="formPadRef"
          v-model="formData"
          :originalData="formDataOriginalValue"
          :readonly="readonly"
          isolated
        >
          <template #default="slotData">
            <slot
              v-bind="slotData"
              :is-creating="isCreating"
              :is-data-change="isDataChange"
            />
          </template>
        </form-pad>
      </VCardText>
      <VCardActions>
        <slot name="action" :operation="operation">
          <VSpacer />
          <VBtn
              color="primary"
              variant="flat"
              :loading="isSaving"
              :disabled="!isDataChange"
              @click="save"
              v-if="!readonly"
          >
            {{ saveCaption }}
          </VBtn>
          <VBtn
              color="error"
              variant="flat"
              :disabled="isSaving"
              @click="cancel"
          >
            {{ !isDataChange ? closeCaption : cancelCaption }}
          </VBtn>
        </slot>
      </VCardActions>
    </VCard>
  </v-dialog>
</template>
