<template>
  <div class="my-1">
    <div>
      <div class="my-1" v-if="modelValue">
        <video v-if="type == 'video'" :src="modelValue" controls />
        <img v-if="type == 'image'" :src="modelValue" />
      </div>
      <button class="btn btn-secondary" @click="show_modal">选择文件</button>
    </div>
    <Modal title="选择文件" ref="modal">
      <slot />
      <MediaUploader @change="reload" />
      <hr>
      <div class="py-3 row mx-2">
        <div @click="select(f)" v-for="f, i in files" :key="i" class="col entry" :class="{selected: selected_item == f}">
          <div class="entry-preview">
            <video v-if="type == 'video' && is_video(f)" :src="f.url" controls />
            <img v-if="type == 'image'" :src="f.url" />
          </div>
          <div v-if="is_image(f) && image_sizes[f.url]" class="image-size">
            {{ image_sizes[f.url].width }}
            x
            {{ image_sizes[f.url].height }}
          </div>
          <div class="filename my-1">
            <label :title="f.filename">
              {{ f.filename }}
            </label>
          </div>
        </div>
        <button v-if="meta && meta.next" @click="load_files(meta.next)">下一页</button>
        <button v-if="meta && meta.previous" @click="load_files(meta.previous)">上一页</button>
        <button @click="reload">刷新</button>
      </div>
    </Modal>
  </div>
</template>

<script>
import MediaUploader from './media-uploader';

export default {
  props: ['type', 'modelValue'],
  emits: ['update:modelValue'],
  components: {
    MediaUploader,
  },
  data: function () {
    return {
      files: [],
      selected_item: null,
      meta: null,
      cur_uri: null,
      image_sizes: {},
    };
  },
  computed: {
    image_only: function() {
      return this.type == 'image';
    },
    video_only: function() {
      return this.type == 'video';
    },
  },
  methods: {
    select: function(f) {
      this.selected_item = f;
    },
    reload: function() {
      this.load_files("/api/v1/asset-file/");
    },
    show_modal: function() {
      this.reload();
      this.$refs.modal.show((ok) => {
        if (ok) {
          this.$emit('update:modelValue', this.selected_item.url);
        }
      });
    },
    load_files: async function(uri) {
      if (uri) {
        this.cur_uri = uri;
      } else {
        uri = this.cur_uri;
      }
      var r = await this.$root.api_get(uri);
      this.files = this.filter_files(r.data.objects);
      this.get_sizes(this.files);
      this.meta = r.data.meta;
    },
    clear: function() {
      this.selected = null;
    },
    filter_files: function(fs) {
      return fs.filter((x) => {
        if (this.type == 'image') {
          return this.is_image(x);
        } else if (this.type == 'video') {
          return this.is_video(x);
        }
        return true;
      });
    },
    is_video: function(x) {
      return this.match_ext(x, ['mp4', 'avi', 'mkv', 'mov', 'webm']);
    },
    is_image: function(x) {
      return this.match_ext(x, ['jpg', 'jpeg', 'png', 'gif', 'ico', 'tif', 'tiff', '.bmp']);
    },
    match_ext: function(item, exts) {
      var fn = item.filename;
      for (var i of exts) {
        if (fn.endsWith('.' + i)) return true;
      }
      return false;
    },
    get_sizes: function(fs) {
      for (const x of fs) {
        var img = new Image();
        img.onload = (evt) => {
          var w = evt.target.width;
          var h = evt.target.height;
          this.image_sizes[x.url] = {
            width: w,
            height: h,
          };
        }
        img.src = x.url;
      }
    },
  },
  mounted() {
  },
}
</script>

<style scoped>
video {
  width: 100%;
  max-height: 100%;
}
div.entry {
  width: 128px;
  border: 1px solid #888;
  margin: 0.2rem 0.2rem 0.2rem 0.2rem;
}

div.entry-preview {
  width: 100%;
  height: 128px;
}

div.filename {
  overflow: hidden;
  max-height: 20px;
}
div.selected {
  border-width: 3px;
  border-color: blue;
}
div.entry img {
  max-height: 100%;
  max-width: 100%;
}
img {
  max-width: 100%;
}
div.image-size {
  color: #bbb;
}
</style>

