<script setup>
import { VueSignaturePad } from "vue-signature-pad";
import { VInput } from "vuetify/components/VInput";
import { ref, computed, useAttrs, watch } from "vue";
import { useAssetFile } from "../../composables/assetFile";
const props = defineProps({
  title: { type: String, required: false, default: "Signature" },
  btnName: { type: String, required: false, default: "Draw Your Signature" },
  titleConfirm: { type: String, required: false, default: "I Accept My Signature" },
  penColor: { type: String, required: false, default: "#303F9F" },
  autoHydrate: { type: Boolean, required: false, default: true }
});
const { hydrateAssetFile } = useAssetFile();
const attrs = useAttrs();
const model = defineModel({ type: [Object, String, null], ...{ default: null } });
const inputRef = ref(null);
const signaturePadRef = ref(null);
const isDialogOpen = ref(false);
const signatureOptions = computed(() => ({
  penColor: props.penColor,
  minWidth: 0.5,
  maxWidth: 4
}));
const normalized = ref(null);
const imageDataUrl = computed(() => {
  const val = normalized.value;
  if (!val?.base64String) return void 0;
  return useAssetFile().ensureDataUrl(val.base64String.trim(), val.fileType || "image/png");
});
const cardVariant = computed(() => {
  return attrs.variant;
});
let syncing = false;
function wrapToAsset(input) {
  if (input == null) return null;
  return typeof input === "string" ? { base64String: input } : input;
}
watch(
  model,
  async (val) => {
    if (syncing) return;
    syncing = true;
    try {
      const asAsset = wrapToAsset(val);
      normalized.value = asAsset;
      if (typeof val === "string") {
        model.value = asAsset;
      }
      if (props.autoHydrate && asAsset?.id != null && !asAsset.base64String) {
        await hydrateAssetFile(asAsset);
        model.value = asAsset;
      }
    } finally {
      syncing = false;
    }
  },
  { immediate: true }
);
const undoSignature = () => signaturePadRef.value?.undoSignature();
const clearSignature = () => signaturePadRef.value?.clearSignature();
const closeDialog = () => {
  isDialogOpen.value = false;
  signaturePadRef.value?.clearSignature();
  signaturePadRef.value?.clearCacheImages?.();
};
const saveSignature = () => {
  isDialogOpen.value = false;
  const result = signaturePadRef.value?.saveSignature();
  if (!result) return;
  const { isEmpty, data } = result;
  if (isEmpty) {
    normalized.value = null;
    model.value = null;
  } else {
    const asset = { base64String: data };
    normalized.value = asset;
    model.value = asset;
  }
};
const openSignatureDialog = async () => {
  if (props.autoHydrate && normalized.value?.id != null && !normalized.value.base64String) {
    await hydrateAssetFile(normalized.value);
    model.value = normalized.value;
  }
  isDialogOpen.value = true;
  const existing = normalized.value?.base64String;
  if (existing) {
    requestAnimationFrame(() => signaturePadRef.value?.fromDataURL(existing));
  }
};
const isValid = computed(() => inputRef.value?.isValid);
const errorMessages = computed(() => inputRef.value?.errorMessages);
defineExpose({
  errorMessages,
  isValid,
  reset: () => inputRef.value?.reset(),
  resetValidation: () => inputRef.value?.resetValidation(),
  validate: () => inputRef.value?.validate()
});
</script>

<template>
  <v-input v-model="model" v-bind="$attrs" ref="inputRef">
    <template #default="{ isReadonly, isDisabled }">
      <v-card class="w-100" flat :variant="cardVariant" :title="props.title">
        <v-card-text v-if="normalized?.base64String">
          <v-img :src="imageDataUrl" cover />
          <v-icon
              class="position-absolute"
              style="top: 8px; right: 8px; z-index: 10;"
              @click="model = null;
  normalized = null"
              v-if="!isReadonly?.value"
          >
            mdi mdi-close-circle
          </v-icon>
        </v-card-text>

        <v-card-actions v-if="!isReadonly?.value">
          <v-btn
              append-icon="mdi mdi-draw-pen"
              block
              class="text-none"
              color="primary"
              variant="flat"
              @click="openSignatureDialog"
              :readonly="isReadonly?.value"
              :disabled="isDisabled?.value"
          >
            {{ props.btnName }}
          </v-btn>
        </v-card-actions>

        <v-dialog v-model="isDialogOpen" height="auto" persistent width="100%">
          <v-card>
            <v-toolbar>
              <v-toolbar-title class="text-no-wrap">
                {{ props.title }}
              </v-toolbar-title>

              <v-btn icon @click="undoSignature">
                <v-icon>fa-solid fa-arrow-rotate-left</v-icon>
              </v-btn>

              <v-btn icon @click="clearSignature">
                <v-icon>fa-solid fa-trash</v-icon>
              </v-btn>

              <v-btn icon @click="closeDialog">
                <v-icon>fa-solid fa-xmark</v-icon>
              </v-btn>
            </v-toolbar>

            <v-card-text>
              <VueSignaturePad
                  ref="signaturePadRef"
                  :options="signatureOptions"
                  height="40vh"
              />
            </v-card-text>

            <v-divider />

            <v-card-actions class="justify-center">
              <v-btn
                  class="text-none"
                  color="success"
                  prepend-icon="fa-solid fa-check"
                  variant="flat"
                  @click="saveSignature"
              >
                {{ props.titleConfirm }}
              </v-btn>
            </v-card-actions>
          </v-card>
        </v-dialog>
      </v-card>
    </template>
  </v-input>
</template>
