<script lang="ts" setup>
import { ref, watch } from 'vue';
import AppBox from './app/AppBox.vue';
import { CancelButton, ClearButton, SaveButton } from './button';
import { dialog } from 'src/stores/utils';

defineExpose({ browse });
const props = defineProps<{
  changeDisabled?: boolean;
  clearButtonDisabled?: boolean;
  clearButton?: boolean;
  hiddenFooter?: boolean;
  defaultUrl?: string;
  onCreate?: boolean;
}>();
const emit = defineEmits<{
  (e: 'save', file: File | null, url: string | null): void;
  (e: 'addImage', file: File | null): void;
  (e: 'removeImage', name: string): void;
  (e: 'submit', name: string): void;
}>();

const imageUrl = defineModel<string>('imageUrl', {
  required: false,
  default: '',
});
const fallbackUrl = defineModel<string>('fallbackUrl', {
  required: false,
  default: '',
});
const dialogState = defineModel<boolean>('dialogState', {
  required: false,
  default: true,
});
const file = defineModel<File | null>('file', {
  required: true,
});
const dataList = defineModel<{ selectedImage: string; list: string[] }>(
  'dataList',
  {
    required: false,
    default: { selectedImage: '', list: [] },
  },
);
const onCreateData = defineModel<{
  selectedImage: string;
  list: { url: string; imgFile: File | null; name: string }[];
}>('onCreateDataList', {
  required: false,
  default: { selectedImage: '', list: [] },
});

const apiBaseUrl = import.meta.env.VITE_API_BASE_URL;
const reader = new FileReader();
const inputFile = (() => {
  const _element = document.createElement('input');
  _element.type = 'file';
  _element.accept = 'image/*';
  _element.addEventListener('change', change);
  return _element;
})();

const selectedImg = ref('');
const tempImage = ref<string | null>('');

reader.addEventListener('load', () => {
  if (typeof reader.result === 'string') {
    tempImage.value = reader.result;
    if (props.onCreate) {
      onCreateData.value.list.push({
        url: reader.result,
        imgFile: file.value,
        name: Date.now().toString(),
      });
      onCreateData.value.selectedImage =
        onCreateData.value.list[onCreateData.value.list.length - 1].name;
      selectedImg.value = reader.result;
    } else {
      emit('addImage', file.value);
    }
  }
});

function browse() {
  inputFile?.click();
}

function change(e: Event) {
  const _element = e.target as HTMLInputElement | null;
  const _file = _element?.files?.[0];

  if (_file) {
    file.value = _file;
    reader.readAsDataURL(_file);
    if (!dialogState.value) {
      emit('save', _file, tempImage.value);
    }
  }
}

async function downloadImage(url: string | null) {
  if (!url) return;
  const res = await fetch(url);
  const blob = await res.blob();

  let extension = '';

  if (blob.type === 'image/jpeg') extension = '.jpg';
  else if (blob.type === 'image/png') extension = '.png';
  else return;

  let a = document.createElement('a');
  a.download = `download${extension}`;
  a.href = window.URL.createObjectURL(blob);
  a.click();
  a.remove();
}

function selectImg(name: string) {
  if (props.onCreate) {
    selectedImg.value = name;
    tempImage.value = name;
    onCreateData.value.selectedImage =
      onCreateData.value.list.find((v) => v.url === name)?.name || '';
  } else {
    selectedImg.value = name.split('/').pop() || '';
    tempImage.value = `${apiBaseUrl}/${name}`;
  }
}

function closeCheckToDefault() {
  let imgNameList: string[];
  let currentSelected: string;
  let inList: boolean;

  if (props.onCreate) {
    imgNameList = onCreateData.value.list.map((v) => v.url || '');
    currentSelected = imageUrl.value;
  } else {
    imgNameList = dataList.value.list.map((v) => v.split('/').pop() || '');
    currentSelected = dataList.value.selectedImage;
  }

  inList = imgNameList.includes(currentSelected);

  if (!inList && currentSelected !== '') {
    selectImg('');
    emit('submit', selectedImg.value);
  }
}

watch(
  () => dialogState.value,
  () => {
    if (dialogState.value) {
      if (props.onCreate) {
        tempImage.value = imageUrl.value;
        selectedImg.value = imageUrl.value;
      } else {
        tempImage.value = `${imageUrl.value}?ts=${Date.now()}`;
        selectedImg.value = dataList.value.selectedImage;
      }
    } else {
      tempImage.value = '';
      selectedImg.value = '';
    }
  },
);

watch(
  () => dataList.value.list,
  (n, o) => {
    if (n.length > o.length) {
      selectImg(n[n.length - 1]);
    }
  },
  { deep: true },
);
</script>
<template>
  <q-dialog v-model="dialogState" @before-hide="closeCheckToDefault">
    <AppBox class="image-dialog-content column">
      <!-- header -->
      <div class="row items-center q-py-sm q-px-md bordered-b">
        <div style="width: 38.61px" />
        <div style="flex: 1"><slot name="title" /></div>
        <div>
          <CancelButton v-close-popup icon-only @click="closeCheckToDefault" />
        </div>
      </div>

      <!-- body -->
      <div class="q-px-lg surface-2 col row full-width">
        <div
          class="image-dialog-body q-my-lg relative-position rounded surface-1 flex items-center"
        >
          <img
            :src="tempImage || fallbackUrl"
            v-if="tempImage || fallbackUrl"
            style="object-fit: contain; width: 100%"
            @error="
              () => {
                tempImage = '';
              }
            "
          />
          <div
            style="object-fit: contain; height: 100%; width: 100%"
            v-if="!tempImage && !fallbackUrl"
          >
            <slot name="error"></slot>
          </div>
          <div class="absolute-top-left q-pa-md">
            <q-btn
              class="upload-image-btn q-mr-md"
              icon="mdi-camera-plus-outline"
              id="btn-add-img"
              size="md"
              unelevated
              round
              v-if="!changeDisabled"
              @click="
                () => {
                  inputFile?.click();
                }
              "
              style="color: hsla(var(--stone-0-hsl) / 0.7)"
            ></q-btn>
            <q-btn
              v-if="!onCreate"
              class="upload-image-btn"
              icon="mdi-download-outline"
              id="btn-download-img"
              size="md"
              unelevated
              round
              @click="downloadImage(tempImage)"
              style="color: hsla(var(--stone-0-hsl) / 0.7)"
            ></q-btn>
          </div>
        </div>

        <div
          v-if="!hiddenFooter"
          class="col q-ml-md q-pt-sm q-my-md"
          style="width: 40em; height: 30em; overflow: auto"
        >
          <div class="row items-center q-gutter-sm">
            <div
              class="rounded surface-1 relative-position"
              :class="{
                'selected-img': selectedImg === '',
              }"
              style="
                object-fit: cover;
                height: 5vw;
                width: 5vw;
                overflow: hidden;
              "
              @click="selectImg('')"
            >
              <slot name="error"></slot>
            </div>

            <template v-if="dataList">
              <div
                v-for="(img, n) in onCreate
                  ? onCreateData.list.map((item) => item.url)
                  : dataList.list"
                :key="n"
                class="rounded surface-1 relative-position"
                :class="{
                  'selected-img':
                    selectedImg && onCreate
                      ? selectedImg === img
                      : selectedImg === img.split('/').pop(),
                }"
                style="height: 5vw; width: 5vw"
                @click="selectImg(img)"
              >
                <q-btn
                  icon="mdi-close"
                  class="absolute-top-right"
                  rounded
                  padding="0"
                  size="sm"
                  style="
                    z-index: 2;
                    top: -5px;
                    right: -5px;
                    background: var(--surface-1);
                    color: hsl(var(--negative-bg));
                  "
                  @click.stop="
                    () => {
                      if (onCreate) {
                        const v = onCreateData.list.splice(n, 1);
                        if (v[0].url === selectedImg) {
                          if (onCreateData.list.length === 0 || n === 0) {
                            selectImg('');
                          } else {
                            selectImg(onCreateData.list[n - 1].url);
                          }
                        }
                      } else {
                        dialog({
                          color: 'negative',
                          icon: 'mdi-alert',
                          title: $t('dialog.title.confirmDelete'),
                          actionText: $t('general.delete'),
                          message: $t('dialog.message.confirmDelete'),
                          action: async () => {
                            $emit('removeImage', img);
                            const index = dataList.list.indexOf(img);
                            if (img.split('/').pop() === selectedImg) {
                              if (dataList.list.length === 0 || index === 0) {
                                selectImg('');
                              } else {
                                selectImg(dataList.list[index - 1]);
                              }
                            }
                          },
                          cancel: () => {},
                        });
                      }
                    }
                  "
                ></q-btn>
                <div
                  class="rounded full-width full-height surface-1"
                  style="overflow: hidden"
                >
                  <img
                    v-if="img"
                    :src="onCreate ? img : `${apiBaseUrl}/${img}`"
                    class=""
                    style="object-fit: cover; height: 100%; width: 100%"
                  />
                </div>
              </div>
            </template>
          </div>
        </div>
      </div>

      <!-- footer -->
      <div
        class="row items-center justify-end q-py-sm q-px-md bordered-t"
        v-if="!hiddenFooter"
      >
        <ClearButton
          outlined
          @click="
            inputFile && (inputFile.value = ''),
              (imageUrl = defaultUrl || fallbackUrl || ''),
              (file = null)
          "
          class="q-px-md q-mr-auto"
          :disabled="
            clearButtonDisabled ||
            imageUrl === fallbackUrl ||
            imageUrl === defaultUrl ||
            !imageUrl
          "
          v-if="clearButton"
        />
        <!-- <CancelButton
          id="btn-cancel-img"
          outlined
          class="q-px-md q-mr-sm"
          @click="
            inputFile && (inputFile.value = ''),
              (tempImage = defaultUrl || fallbackUrl || ''),
              (file = null)
          "
          v-close-popup
        /> -->
        <SaveButton
          id="btn-save-img"
          outlined
          :disabled="dataList.selectedImage === selectedImg"
          :label="$t('general.apply')"
          @click="$emit('submit', selectedImg)"
        />
        <!-- @click="$emit('save', inputFile?.files?.[0] || null, tempImage)" -->
      </div>
    </AppBox>
  </q-dialog>
</template>

<style scoped>
.image-dialog-content {
  padding: 0;
  border-radius: var(--radius-2);
  flex-wrap: nowrap;
}

@media (min-width: 768px) {
  .image-dialog-content {
    max-width: 70%;
  }
}

.image-dialog-body {
  /* overflow-y: auto;
  background-color: var(--surface-1) !important;
  position: relative;
  display: flex;
  flex-direction: column;
  flex: 1; */
  overflow: hidden;
  width: 30em;
  height: 30em;
}

.upload-image-btn {
  transition: 0.3s background-color ease-in-out;
  background-color: hsla(0 0% 0% / 0.2);

  backdrop-filter: blur(1px);

  &:not(:hover) {
    color: hsla(0 0% 40% / 1);
    background-color: hsla(0 0% 0% / 0.2);
  }
}

.image-container {
  width: 100%;
  height: calc(100vh - 200px);
  min-height: 480px;

  & > :deep(*) {
    height: 100%;
    width: 100%;
  }
}

.image-container > :deep(*:not(:first-child)) {
  display: none;
}

.close-btn {
  color: hsl(var(--negative-bg));
  background-color: hsla(var(--negative-bg) / 0.1);

  &.dark {
    background-color: transparent;
    border: 1px solid hsl(var(--negative-bg));
  }
}

.selected-img {
  position: relative;
  border: 2px solid hsl(var(--info-bg));
}

.selected-img:before {
  content: ' ';
  position: absolute;
  z-index: 1;
  top: 0px;
  left: 0px;
  right: 0px;
  bottom: 0px;
  border: 2px solid var(--surface-1);
  border-radius: 5px;
}
</style>
