<template>
  <div
    class="c-image iconfont has-bg"
    :class="className"
    :style="styles"
  >
    <template v-if="!isSnapping">
      <template v-if="isSlide">
        <transition name="slide">
          <div
            v-if="toggle"
            key="first"
            class="c-image__slider has-bg"
            :style="slideStyles"
          />
          <div
            v-else
            key="second"
            class="c-image__slider has-bg"
            :style="slideStyles"
          />
        </transition>
      </template>
      <template v-if="isFlip">
        <div
          class="c-image__flipper"
          :class="{ toggle: toggle }"
        >
          <div
            class="front has-bg"
            :style="flipFrontStyles"
          />
          <div
            class="back has-bg"
            :style="flipBackStyles"
          />
        </div>
      </template>
      <template v-if="isSectionFlip">
        <div
          v-for="(sectionStyle, index) in sectionStyles"
          :key="index"
          class="c-image__flipper"
          :class="{ toggle: toggle }"
        >
          <div
            class="front"
            :style="[flipFrontStyles, sectionStyle]"
          />
          <div
            class="back"
            :style="[flipBackStyles, sectionStyle]"
          />
        </div>
      </template>
    </template>
  </div>
</template>

<script>
import { getThumbnailUrl } from '@/api/asset'
import { WidgetType } from '../constant'
import { switchToNext } from '../utils'

export default {
  name: WidgetType.IMAGE,
  inject: ['control'],
  props: {
    node: {
      type: Object,
      default: null
    }
  },
  data () {
    return {
      img: null,
      frontImage: null,
      backImage: null,
      toggle: false
    }
  },
  computed: {
    isSnapping () {
      return this.control.snapping
    },
    styles () {
      const {
        width,
        height,
        radius
      } = this.node
      return {
        width: `${width}px`,
        height: `${height}px`,
        'font-size': `${Math.min(width, height) / 3 | 0}px`,
        'border-radius': `${radius}px`,
        'background-image': !this.isEmpty && this.isNormal ? `url(${getThumbnailUrl(this.img)})` : 'none'
      }
    },
    className () {
      return this.isSnapping ? {
        empty: this.isEmpty
      } : {
        empty: this.isEmpty,
        slide: this.isSlide,
        fade: this.isFade,
        flip: this.isFlip || this.isSectionFlip
      }
    },
    isEmpty () {
      return !this.img
    },
    slideStyles () {
      return {
        'background-image': this.img ? `url(${getThumbnailUrl(this.img)})` : 'none'
      }
    },
    flipFrontStyles () {
      return {
        'background-image': this.frontImage ? `url(${getThumbnailUrl(this.frontImage)})` : 'none'
      }
    },
    flipBackStyles () {
      return {
        'background-image': this.backImage ? `url(${getThumbnailUrl(this.backImage)})` : 'none'
      }
    },
    isNormal () {
      const { animation } = this.node
      return this.isSnapping || animation === 'none' || animation === 'fade'
    },
    isFade () {
      return this.node.animation === 'fade'
    },
    isSlide () {
      return this.node.animation === 'slide'
    },
    isFlip () {
      return this.node.animation === 'flip'
    },
    isSectionFlip () {
      return this.node.animation === 'section-flip'
    },
    sctionWidth () {
      return this.width / 10
    },
    sectionStyles () {
      const { width } = this.node
      const offset = width / 10
      const styles = []
      for (let i = 0; i < 10; i++) {
        styles.push({
          'background-size': `${width}px 100%`,
          'background-position-x': `-${offset * i}px`
        })
      }
      return styles
    }
  },
  watch: {
    'node.sources' () {
      this.reset()
    },
    'node.interval' (val) {
      if (this.node.sources.length > 1) {
        clearTimeout(this.$timer)
        this.$timer = setTimeout(this.toggleImage, val * 1000)
      }
    },
    isSnapping (val) {
      if (this.node.sources.length > 1) {
        if (val) {
          clearTimeout(this.$timer)
        } else {
          this.$timer = setTimeout(this.toggleImage, val * 1000)
        }
      }
    }
  },
  created () {
    this.$timer = -1
    this.reset()
  },
  beforeDestroy () {
    clearTimeout(this.$timer)
  },
  methods: {
    reset () {
      this.$index = -1
      this.choose()
      this.changeFlip()
    },
    changeFlip () {
      if (this.toggle) {
        this.backImage = this.img
      } else {
        this.frontImage = this.img
      }
    },
    toggleImage () {
      this.choose()
      this.toggle = !this.toggle
      this.changeFlip()
    },
    choose () {
      const { sources, interval, toggleType } = this.node
      clearTimeout(this.$timer)

      this.$index = switchToNext(toggleType, sources, this.$index)
      this.img = sources[this.$index]

      if (sources.length > 1) {
        this.$timer = setTimeout(this.toggleImage, interval * 1000)
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.c-image {
  position: relative;
  display: inline-block;
  overflow: hidden;

  &.empty {
    display: inline-flex;
    justify-content: center;
    align-items: center;
    background-color: rgba(255, 255, 255, 0.8);

    &::before {
      content: "\e612";
      font-size: inherit;
    }
  }

  &.fade {
    transition: background-image 1s;
  }

  &.slide {
    .slide-enter {
      transform: translateX(100%);
    }
    .slide-leave-to {
      transform: translateX(-100%);
    }

    .c-image__slider {
      position: absolute;
      width: 100%;
      height: 100%;
      transition: transform 0.3s;
    }
  }

  &.flip {
    display: inline-flex;

    .c-image__flipper {
      position: relative;
      display: inline-flex;
      flex: 1 0 0;
      transition: transform 1s;
      transform-style: preserve-3d;

      &.toggle {
        transform: rotateY(180deg);
      }

      .front,
      .back {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        backface-visibility: hidden;
      }

      .back {
        transform: rotateY(180deg);
      }
    }
  }
}
</style>
