<template>
  <div class="q-mb-sm">
  <div
    class="relative-position"
    :style="{
      width: sizePx,
      height: sizePx, 
      display: 'block'
    }"
    >
    <q-file
      ref="imgFileSelector"
      v-model="imageFile"
      :style="{ display: 'none' }"
      @update:model-value="handleUpload()"
      :filter="checkImgType"
      :accept="allowedMimeTypes.join(', ')"
    />
    <q-icon
      v-if="modelValue === '' || modelValue === undefined || modelValue === null"
      name="mdi-camera-plus-outline"
      class="absolute-full fit text-grey-4"
      :style="{ fontSize: String(iconsize) + 'px'}"
      @click = "imgFileSelectorClick"
    />
    <q-img
      v-else
      fit="cover"
      :src="modelValue"
      :style="{
        height: sizePx,
        maxWidth: sizePx,
        borderRadius: avatar ? String(size/2) + 'px' : 'var(--top-radius)',
      }"
      @click="imgFileSelectorClick"
    />

    <q-btn
      v-if="modelValue"
      icon="mdi-delete-outline"
      round
      color="primary"
      size="md"
      style="border: solid 2px white; bottom: -16px; right: -16px;"
      class="absolute-bottom-right"
      @click="deleteImage"
    />
  </div>
</div>
</template>

<script setup lang="ts">
  import { ref, Ref, computed } from 'vue' // eslint-disable-line
  import { QFile } from 'quasar'
  import imageCompression from 'browser-image-compression'

  const modelValue = defineModel<string | null>()

  const props = defineProps<{
    size?: number
    iconsize?: number
    avatar?: boolean
  }>()

  const compressionOptions = {
    maxSizeMB: 0.5,        // Max size ~500 KB
    maxWidthOrHeight: 1200, // Max resolution
    useWebWorker: true,     // Performance
    fileType: 'image/jpeg'  // Output format
  }

  const imageFile = ref(null) // file-from selector
  const imgFileSelector = ref() as Ref<QFile> // input file DOM
  const size = ref<number>(props.size ? props.size  : 100)
  const iconsize = ref<number>(props.iconsize ? props.iconsize  : 75)

  const sizePx = computed(() => {
    return String(size.value) + 'px'
  })

  async function handleUpload() {
    if (imageFile.value) {
      try {
        const compressedFile = await imageCompression(
          imageFile.value, 
          compressionOptions
        )
        
        const img = await imgToBase64(compressedFile);
        modelValue.value = typeof img === 'string' ? img : ''
      } catch (error) {
        console.error('Image error compression:', error)
        const img = await imgToBase64(imageFile.value)
        modelValue.value = typeof img === 'string' ? img : ''
      }
    }
  }

  function imgFileSelectorClick () {
    imgFileSelector.value.pickFiles()
  }

  function deleteImage () {
    imageFile.value = null
    modelValue.value = null
  }

  function imgToBase64 (file: File): Promise<string | ArrayBuffer | null> {
    const reader: FileReader = new FileReader()
    reader.readAsDataURL(file)

    return new Promise((resolve, reject) => {
      reader.onerror = () => {
        reader.abort()
        reject(new Error('Something went wrong'))
      }

      reader.onload = () => resolve(reader.result)
    })
  }

  const allowedMimeTypes = [
    'image/jpeg',
    'image/png',
    'image/bmp',
    'image/webp',
    'image/gif'
  ]
  
  function checkImgType (files: File[]): File[] {
    return files.filter((file: File) => allowedMimeTypes.includes(file.type))
  }
</script>

<style scope>
</style>
