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

defineExpose({ browse });
defineProps<{
  changeDisabled?: boolean;
  clearButtonDisabled?: boolean;
  clearButton?: boolean;
  hiddenFooter?: boolean;
  defaultUrl?: string;
}>();
const emit = defineEmits<{
  (e: 'save', file: File | null, url: string | null): void;
  (e: 'clear'): 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 reader = new FileReader();
const inputFile = (() => {
  const _element = document.createElement('input');
  _element.type = 'file';
  _element.accept = 'image/*';
  _element.addEventListener('change', change);
  return _element;
})();

reader.addEventListener('load', () => {
  if (typeof reader.result === 'string') {
    imageUrl.value = reader.result;
    if (!dialogState.value) emit('save', file.value, imageUrl.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);
  }
}

async function downloadImage(url: string) {
  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();
}
</script>
<template>
  <q-dialog v-model="dialogState">
    <AppBox class="image-dialog-content">
      <div class="row items-center q-py-sm q-px-md bordered-b">
        <div style="flex: 1"><slot name="title" /></div>
        <div>
          <q-btn
            round
            flat
            icon="mdi-close"
            padding="xs"
            class="close-btn"
            :class="{ dark: $q.dark.isActive }"
            v-close-popup
          />
        </div>
      </div>
      <div class="image-dialog-body">
        <img
          :src="imageUrl || fallbackUrl"
          v-if="imageUrl || fallbackUrl"
          class="image-container"
          style="object-fit: contain"
          @error="imageUrl = ''"
        />
        <div class="image-container" v-if="!imageUrl && !fallbackUrl">
          <slot name="error"></slot>
        </div>
        <div style="position: fixed; padding: var(--size-2)">
          <q-btn
            class="upload-image-btn q-mr-md"
            icon="mdi-camera-outline"
            size="md"
            unelevated
            round
            v-if="!changeDisabled"
            @click="inputFile?.click()"
            style="color: hsla(var(--stone-0-hsl) / 0.7)"
          ></q-btn>
          <q-btn
            class="upload-image-btn"
            icon="mdi-download-outline"
            size="md"
            unelevated
            round
            @click="downloadImage(imageUrl)"
            style="color: hsla(var(--stone-0-hsl) / 0.7)"
          ></q-btn>
        </div>
      </div>
      <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),
              $emit('clear')
          "
          class="q-px-md q-mr-auto"
          :disabled="
            clearButtonDisabled ||
            imageUrl === fallbackUrl ||
            imageUrl === defaultUrl ||
            !imageUrl
          "
          v-if="clearButton"
        />
        <CancelButton
          outlined
          class="q-px-md q-mr-sm"
          @click="
            inputFile && (inputFile.value = ''),
              (imageUrl = defaultUrl || fallbackUrl || ''),
              (file = null)
          "
          v-close-popup
        />
        <SaveButton
          outlined
          @click="$emit('save', inputFile?.files?.[0] || null, imageUrl)"
        />
      </div>
    </AppBox>
  </q-dialog>
</template>

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

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

.image-dialog-body {
  overflow-y: auto;
  background-color: var(--surface-2) !important;
  position: relative;
  display: flex;
  flex-direction: column;
  flex: 1;
  height: calc(100vh - 200px);
}

.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));
  }
}
</style>
