<template>
  <section class="o-file-uploader">
    <q-file v-model="value" class="file-uploader"
            :accept="accept"
            :readonly="readonly"
            outlined
            @update:model-value="updateFiles" >
      <section class="row col-12 justify-center items-center text-info panel">
        <section class="col-12 text-center tips">
          <div class="row items-center rounded-borders" v-if="fileIcon">
            <div class="col-auto" style="width: 4rem" v-if="leading">
              <template v-if="loading">
                <q-spinner-puff size="3rem" color="primary" />
              </template>
              <template v-else>
                <q-icon :name="icon || fileIcon" color="green" size="2rem" v-if="done" />
                <q-icon name="error" color="red" size="2rem" v-else />
              </template>
            </div>
            <div class="row col justify-center relative-position">
              <img :src="src" />
            </div>
            <div class="col-12" v-if="error">
              <div class="text-red text-bold">
                {{error}}
              </div>
              <div class="q-mt-md text-tips limit" v-if="!hideLimit">
                <template v-for="(item, index) in accept.split(',')" :key="index">
                  <o-badge>{{item.replaceAll('.', '').toUpperCase()}}</o-badge>
                </template>
                <q-chip square dense>
                  <q-avatar color="red" text-color="white">Max</q-avatar>
                  <span>{{maxSize / (1024 * 1024)}}M</span>
                </q-chip>
              </div>
            </div>
          </div>
          <section class="text-center tips" v-else-if="loading">
            <div>
              <q-spinner-puff size="4rem" color="primary" />
            </div>
          </section>
          <div v-else>
            <template v-if="preview">
              <img :src="preview" referrerpolicy="no-referrer" />
            </template>
            <template v-else>
              <div class="text-tips">
                <q-icon name="cloud_upload" size="3rem" />
              </div>
              <div class="text-tips">
                <span>{{ label || $t('book.uploader.label') }}</span>
              </div>
              <div class="q-mt-md limit" :class="{ 'text-red': error }"  v-if="!hideLimit">
                <template v-for="(item, index) in accept.split(',')" :key="index">
                  <o-badge>{{item.replaceAll('.', '').toUpperCase()}}</o-badge>
                </template>
                <q-chip square dense>
                  <q-avatar color="red" text-color="white">Max</q-avatar>
                  <span>{{maxSize / (1024 * 1024)}}M</span>
                </q-chip>
              </div>
            </template>
          </div>
        </section>
      </section>
    </q-file>
    <div class="text-tips q-mt-sm tips" v-if="tips">
      {{ tips }}
    </div>

    <slot></slot>
  </section>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue'
import { fileService } from 'src/api/service/remote'
import { getErrorMessage } from 'src/utils/request'

const props = defineProps({
  type: {
    type: String,
    default: `image`
  },
  accept: {
    type: String,
    default: `*`
  },
  maxSize: {
    type: Number,
    default: 100 * 1024 * 1024
  },
  icon: {
    type: String,
    default: ''
  },
  label: {
    type: String,
    default: ''
  },
  preview: {
    type: String,
    default: ''
  },
  tips: {
    type: String,
    default: ''
  },
  readonly: {
    type: Boolean,
    default: false
  },
  leading: {
    type: Boolean,
    default: false
  },
  refId: {
    type: String,
    default: ''
  },
  refType: {
    type: String,
    default: ''
  },
  reset: {
    type: Boolean,
    default: false
  },
  hideLimit: {
    type: Boolean,
    default: false
  },
})
const emit = defineEmits(['uploaded'])

const value = ref(null)
const selectedFile = ref<File>()
const src = ref('')

const loading = ref(false)
const done = ref(false)
const error = ref('')

const fileIcon = computed(() => {
  if (selectedFile.value && selectedFile.value.type) {
    const type = selectedFile.value.type
    if (type.indexOf('image/') === 0) {
      return 'image'
    } else if (type.indexOf('video/') === 0) {
      return 'videocam'
    } else if (type.indexOf('audio/') === 0) {
      return 'audiotrack'
    } else {
      return 'attach_file'
    }
  } else {
    return ''
  }
})

function updateFiles (file: File) {
  error.value = ''
  selectedFile.value = file
  src.value = URL.createObjectURL(file)
  if (props.maxSize > 0) {
    const size = file.size
    if (size > props.maxSize) {
      console.log('maxSize', size)
      error.value = '文件大小超出限制，请重新选择'
      return
    }
  }

  upload(file)
}

function upload(file: File) {
  loading.value = true
  const ref = {
    refId: props.refId,
    refType: props.refType,
  }
  fileService.upload(file, ref).then(res => {
    done.value = true
    emit('uploaded', res)

    if (props.reset) {
      selectedFile.value = undefined
      src.value = ''
    }
  }).catch(err => {
    error.value = getErrorMessage(err)
  }).finally(() => {
    loading.value = false
  })
}

</script>

<style lang="scss">
.o-file-uploader {
  position: relative;

  .file-uploader {
    min-height: 160px;
    min-width: 160px;
  }

  .tips {
    font-size: 12px;
    text-align: center;
  }

  .q-field {
    margin: 0 !important;

    &--readonly {
      .q-field__control:hover {
        background: transparent !important;
      }
    }
  }

  .q-field__native {
    align-items: start!important;
    z-index: 1;
    padding: 0 !important;

    div {
      display: none;
      background: red;
    }
  }

  .q-field__control {
    height: 100%;
    padding: 0 6px;

    &:before {
      border-style: dashed;
    }
  }

  .panel {
    position: absolute;
    left: 0;
    right: 0;
    width: 100%;
    height: 100%;
    //cursor: pointer;
    z-index: 0;

    img {
      max-height: 160px;
      max-width: 100%;
    }

    .limit {
      font-size: 0.9rem;
      .q-chip {
        height: 20px;
        margin: 0 4px 2px 4px;

        .q-avatar {
          padding: 0 4px;
          width: unset;
          height: 20px;
        }

        span {
          font-size: 0.9rem;
        }
      }
    }
  }
}
</style>
