<template>
  <Modal
    :class="prefixCls"
    v-model="modalIsShow"
    title="图片预览"
    :mask-closable="false"
    fullscreen
    footer-hide
    @on-visible-change="visibleChange"
  >
    <div slot="header"></div>
    <div :class="[`${prefixCls}-close`]" @click="modalIsShow = false">
      <i class="el-icon-circle-close"></i>
      <Icon type="ios-close" />
    </div>
    <div :class="[`${prefixCls}-header`]" v-if="!headerHide">
      <h3>{{ curFile.name }}</h3>
      <div :class="[`${prefixCls}-index`]">
        {{ this.curIndex + 1 }} / {{ this.lastIndex }}
      </div>
    </div>
    <div :class="[`${prefixCls}-body`]" ref="ReviewBody">
      <div
        :class="[`${prefixCls}-guide`, `${prefixCls}-guide-prev`]"
        @click="showPrev"
      >
        <Icon type="ios-arrow-back" />
      </div>
      <div
        :class="[`${prefixCls}-guide`, `${prefixCls}-guide-next`]"
        @click="showNext"
      >
        <Icon type="ios-arrow-forward" />
      </div>
      <div
        :class="[
          `${prefixCls}-imgs`,
          { [`${prefixCls}-imgs-nosition`]: nosition }
        ]"
        :style="styles"
        v-move-ele.prevent="{ mouseMove }"
      >
        <img :src="curFile.url" :alt="curFile.name" ref="PreviewImgDetail" />
      </div>
    </div>
    <div :class="[`${prefixCls}-footer`]">
      <ul>
        <li title="合适大小" @click="toOrigin">
          <Icon type="md-expand" />
        </li>
        <li
          title="放大"
          @click="toMagnify"
          :class="{
            'li-disabled': transform.scale === maxScale
          }"
        >
          <Icon type="md-add-circle" />
        </li>
        <li
          title="缩小"
          @click="toShrink"
          :class="{
            'li-disabled': transform.scale === minScale
          }"
        >
          <Icon type="md-remove-circle" />
        </li>
        <li title="旋转" @click="toRotate">
          <Icon type="ios-refresh-circle" />
        </li>
      </ul>
    </div>
  </Modal>
</template>

<script>
import MoveEle from "./move-ele";

const prefixCls = "cc-image-preview";

export default {
  name: "image-preview",
  props: {
    imageList: {
      type: Array,
      default() {
        return [];
      }
    },
    initIndex: {
      type: Number,
      default: 0
    },
    headerHide: {
      type: Boolean,
      default: false
    },
    loop: {
      type: Boolean,
      default: false
    }
  },
  directives: {
    MoveEle
  },
  data() {
    return {
      prefixCls,
      modalIsShow: false,
      curFile: { name: "", url: null },
      curIndex: 0,
      minScale: 0.2,
      maxScale: 3,
      styles: { width: "", height: "", top: "", left: "", transform: "" },
      initWidth: 500,
      transform: {
        scale: 1,
        rotate: 0
      },
      nosition: false
    };
  },
  computed: {
    isFirst() {
      return this.curIndex === 0;
    },
    isLast() {
      return this.lastIndex - 1 === this.curIndex;
    },
    lastIndex() {
      return this.imageList.length;
    }
  },
  // watch: {
  //   curIndex: {
  //     immediate: true,
  //     handler(val, oldVal) {
  //       this.curFileChange(val);
  //     }
  //   }
  // },
  mounted() {
    this.registfileLoad();
  },
  methods: {
    initData() {
      if (!this.imageList.length) return;
      this.curIndex = this.initIndex;
      this.curFileChange(this.curIndex);
    },
    visibleChange(visible) {
      if (!visible) return;
      this.initData();
    },
    curFileChange(val) {
      const index = val || 0;
      this.nosition = true;
      this.curFile = this.imageList[index];
    },
    registfileLoad() {
      const imgDom = this.$refs.PreviewImgDetail;

      imgDom.onload = () => {
        const { naturalWidth, naturalHeight } = imgDom;
        const imageSize = this.getImageSizePos({
          win: {
            width: this.$refs.ReviewBody.clientWidth,
            height: this.$refs.ReviewBody.clientHeight
          },
          img: {
            width: naturalWidth,
            height: naturalHeight
          },
          rotate: 0
        });

        this.styles = Object.assign(this.styles, {
          width: imageSize.width + "px",
          height: imageSize.height + "px",
          top: imageSize.top + "px",
          left: imageSize.left + "px",
          transform: ""
        });
        this.transform = {
          scale: 1,
          rotate: 0
        };
        setTimeout(() => {
          this.nosition = false;
        }, 100);
      };
    },
    getImageSizePos({ win, img, rotate }) {
      const imageSize = {
        width: 0,
        height: 0,
        top: 0,
        left: 0
      };
      const isHorizontal = !!(rotate % 180);

      const rateWin = isHorizontal
        ? win.height / win.width
        : win.width / win.height;
      const hwin = isHorizontal
        ? {
            width: win.height,
            height: win.width
          }
        : win;

      const rateImg = img.width / img.height;

      if (rateImg <= rateWin) {
        imageSize.height = Math.min(hwin.height, img.height);
        imageSize.width = Math.floor(
          (imageSize.height * img.width) / img.height
        );
      } else {
        imageSize.width = Math.min(hwin.width, img.width);
        imageSize.height = Math.floor(
          (imageSize.width * img.height) / img.width
        );
      }
      imageSize.left = (win.width - imageSize.width) / 2;
      imageSize.top = (win.height - imageSize.height) / 2;
      return imageSize;
    },
    cancel() {
      this.modalIsShow = false;
    },
    open() {
      this.modalIsShow = true;
    },
    showPrev() {
      if (this.isFirst) {
        if (this.loop) {
          this.curIndex = this.lastIndex - 1;
        } else {
          this.$emit("on-page-prev");
          return;
        }
      } else {
        this.curIndex -= 1;
      }
      this.$emit("on-prev", this.curIndex);
      this.curFileChange(this.curIndex);
    },
    showNext() {
      if (this.isLast) {
        if (this.loop) {
          this.curIndex = 0;
        } else {
          this.$emit("on-page-next");
          return;
        }
      } else {
        this.curIndex += 1;
      }
      this.$emit("on-next", this.curIndex);
      this.curFileChange(this.curIndex);
    },
    // dome-move
    mouseMove({ left, top }) {
      this.styles.left = left + "px";
      this.styles.top = top + "px";
    },
    setStyleTransform() {
      const { scale, rotate } = this.transform;
      this.styles.transform = `scale(${scale}, ${scale}) rotate(${rotate}deg)`;
    },
    toOrigin() {
      this.transform.scale = 1;
      this.setStyleTransform();
    },
    toMagnify() {
      const scale = (this.transform.scale * 1.2).toFixed(2);
      this.transform.scale = scale >= this.maxScale ? this.maxScale : scale;
      this.setStyleTransform();
    },
    toShrink() {
      const scale = (this.transform.scale * 0.75).toFixed(2);
      this.transform.scale = scale <= this.minScale ? this.minScale : scale;
      this.setStyleTransform();
    },
    toRotate() {
      this.transform.rotate = this.transform.rotate + 90;
      this.setStyleTransform();
      // 调整图片尺寸
      const { naturalWidth, naturalHeight } = this.$refs.PreviewImgDetail;
      const imageSize = this.getImageSizePos({
        win: {
          width: this.$refs.ReviewBody.clientWidth,
          height: this.$refs.ReviewBody.clientHeight
        },
        img: {
          width: naturalWidth,
          height: naturalHeight
        },
        rotate: this.transform.rotate
      });

      this.styles = Object.assign(this.styles, {
        width: imageSize.width + "px",
        height: imageSize.height + "px",
        top: imageSize.top + "px",
        left: imageSize.left + "px"
      });
      // 360度无缝切换到0度
      setTimeout(() => {
        if (this.transform.rotate >= 360) {
          this.nosition = true;
          this.transform.rotate = 0;
          this.setStyleTransform();
          setTimeout(() => {
            this.nosition = false;
          }, 100);
        }
      }, 200);
    }
  }
};
</script>
