<template>
  <!-- Root element of PhotoSwipe. Must have class pswp. -->
  <div
    class="pswp vux-previewer"
    tabindex="-1"
    role="dialog"
    aria-hidden="true"
  >
    <!-- Background of PhotoSwipe.
          It's a separate element as animating opacity is faster than rgba(). -->
    <div class="pswp__bg" />
    <!-- Slides wrapper with overflow:hidden. -->
    <div class="pswp__scroll-wrap">
      <!-- Container that holds slides.
          PhotoSwipe keeps only 3 of them in the DOM to save memory.
          Don't modify these 3 pswp__item elements, data is added later on. -->
      <div class="pswp__container">
        <div class="pswp__item" />
        <div class="pswp__item" />
        <div class="pswp__item" />
      </div>
      <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
      <div class="pswp__ui pswp__ui--hidden">
        <div class="pswp__top-bar">
          <!--  Controls are self-explanatory. Order can be changed. -->
          <div class="pswp__counter" />
          <button
            class="pswp__button pswp__button--close"
            title="Close (Esc)"
          />
          <button
            class="pswp__button pswp__button--share"
            title="Share"
          />
          <button
            class="pswp__button pswp__button--fs"
            title="Toggle fullscreen"
          />
          <button
            class="pswp__button pswp__button--zoom"
            title="Zoom in/out"
          />
          <!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
          <!-- element will get class pswp__preloader--active when preloader is running -->
          <div class="pswp__preloader">
            <div class="pswp__preloader__icn">
              <div class="pswp__preloader__cut">
                <div class="pswp__preloader__donut" />
              </div>
            </div>
          </div>
        </div>
        <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
          <div class="pswp__share-tooltip" />
        </div>
        <button
          class="pswp__button pswp__button--arrow--left"
          title="Previous (arrow left)"
        />
        <button
          class="pswp__button pswp__button--arrow--right"
          title="Next (arrow right)"
        />
        <div class="pswp__caption">
          <div class="pswp__caption__center" />
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import PhotoSwipe from 'photoswipe/dist/photoswipe'
import UI from 'photoswipe/dist/photoswipe-ui-default'

export default {
  props: {
    // 结构 list:[{src: '图片地址', w: 600,h: 400}]
    list: {
      type: Array,
      required: true
    },
    index: {
      type: Number,
      default: 0
    },
    options: {
      type: Object,
      default () {
        return {}
      }
    }
  },
  data () {
    return {
      // 预览预判数组 结构[{src: "图片地址",w: 100, h: 100}]
      imgList: [],
      imgPromise: {}
    }
  },
  watch: {
    list: {
      /**
       * 后续比如ajax、其他情况在赋值给list的情况下。进行初始化加载新的图片
       */
      handler: function (val, oldVal) {
        this.loadingImage()
      },
      deep: true
    }
  },
  // 参数 list 有初始值的情况下，进行初始化加载图片
  created () {
    this.loadingImage()
  },
  methods: {
    init (index) {
      // 合并配置
      let options = Object.assign({
        history: false,
        shareEl: false,
        tapToClose: true,
        index: index
      }, this.options)
      this.photoswipe = new PhotoSwipe(this.$el, UI, this.imgList, options)
      this.photoswipe.init()
      this.photoswipe.listen('close', () => {
        this.$emit('on-close')
      })
    },
    /**
     * 通过 this.$nextTick + promise.then 宏任务和微任务的优先级来确保 this.imgPromise[index] 不是 undefined。
     * 保证点击的图片加载完成之后才调用 this.init() 方法
     */
    show (index) {
      index = /\d/.test(index) ? index : 0
      this.$nextTick(() => {
        this.imgPromise[index].then((img) => {
          this.init(index)
        })
      })
    },
    close () {
      this.photoswipe.close()
    },
    /**
     * 加载 this.list 传进来的图片。包装成 promise 图片对象 imgPromise。后续 调用 show
     * 方法是 通过 promise.then 确保图片 加载完成才显示
     */
    loadingImage() {
      this.list.forEach((element, index) => {
        let p = new Promise((resolve, reject) => {
          /* global Image */
          const _img = new Image()
          _img.onload = (e) => {
          // 往预览图片数组增加加载完成的图片
            this.imgList[index] = {
              src: element.src,
              w: e.target.width,
              h: e.target.height
            }
            resolve(_img)
          }
          // 设置图片地址
          _img.src = element.src
        })
        this.imgPromise[index] = p
      })
    }
  }
}
</script>
