<template>
  <transition name="fade">
    <div
      v-if="typeof index === 'number'"
      class="light-gallery"
      @touchstart="touchstartHandler"
      @touchmove="touchmoveHandler"
      @touchend="touchendHandler"
    >
      <div
        class="light-gallery__modal"
        :style="`background: ${background}`"
      >
        <div class="light-gallery__container">
          <ul class="light-gallery__content">
            <li
              v-for="(image, imageIndex) in images"
              :key="imageIndex"
              :style="`transform: translate3d(${currentIndex * -100}%, 0px, 0px);`"
              class="light-gallery__image"
            >
              <img
                v-if="preload(imageIndex)"
                :src="images[imageIndex]"
              >
            </li>
          </ul>
        </div>
        <button
          v-if="currentIndex > 0"
          class="light-gallery__prev"
          :style="`background: ${background}`"
          @click="prev()"
        >
          <svg>
            <polyline
              points="30 10 10 30 30 50"
              stroke-width="4"
              stroke-linecap="butt"
              fill="none"
              stroke-linejoin="round"
              :stroke="interfaceColor"
            />
          </svg>
        </button>
        <button
          v-if="currentIndex + 1 < images.length"
          class="light-gallery__next"
          :style="`background: ${background}`"
          @click="next()"
        >
          <svg>
            <polyline
              points="14 10 34 30 14 50"
              stroke-width="4"
              stroke-linecap="butt"
              fill="none"
              stroke-linejoin="round"
              :stroke="interfaceColor"
            />
          </svg>
        </button>
        <button
          class="light-gallery__close"
          :style="`background: ${background}`"
          @click="close()"
        >
          <svg
            width="30"
            height="30"
          >
            <g
              stroke-width="4"
              :stroke="interfaceColor"
            >
              <line
                x1="5"
                y1="5"
                x2="25"
                y2="25"
              />
              <line
                x1="5"
                y1="25"
                x2="25"
                y2="5"
              />
            </g>
          </svg>
        </button>
      </div>
    </div>
  </transition>
</template>

<script>
const keyMap = {
  LEFT: 37,
  RIGHT: 39,
  ESC: 27,
};

export default {
  props: {
    images: {
      type: Array,
      default: () => [],
    },
    index: {
      type: Number,
      default: 1,
    },
    disableScroll: {
      type: Boolean,
      default: false,
    },
    background: {
      type: String,
      default: 'rgba(0, 0, 0, 0.8)',
    },
    interfaceColor: {
      type: String,
      default: 'rgba(255, 255, 255, 0.8)',
    },
  },
  data() {
    return {
      currentIndex: this.index,
      bodyOverflowStyle: document.body.style.overflow,
      touch: {
        count: 0,
        x: 0,
        y: 0,
        multitouch: false,
        flag: false,
      },
    };
  },
  computed: {},
  watch: {
    index(val) {
      this.currentIndex = val;

      if (this.disableScroll && typeof val === 'number') {
        document.body.style.overflow = 'hidden';
      } else if (this.disableScroll && !val) {
        document.body.style.overflow = this.bodyOverflowStyle;
      }
    },
  },
  mounted() {
    this.bindEvents();
  },
  beforeDestroy() {
    if (this.disableScroll) {
      document.body.style.overflow = this.bodyOverflowStyle;
    }
    this.unbindEvents();
  },
  methods: {
    close() {
      this.$emit('close');
    },
    prev() {
      if (this.currentIndex === 0) return;
      this.currentIndex -= 1;
      this.$emit('slide', { index: this.currentIndex });
    },
    next() {
      if (this.currentIndex === this.images.length - 1) return;
      this.currentIndex += 1;
      this.$emit('slide', { index: this.currentIndex });
    },
    preload(imageIndex) {
      return imageIndex === this.currentIndex
       || imageIndex === this.currentIndex - 1
       || imageIndex === this.currentIndex + 1;
    },
    bindEvents() {
      document.addEventListener('keydown', this.keyDownHandler, false);
    },
    unbindEvents() {
      document.removeEventListener('keydown', this.keyDownHandler, false);
    },
    touchstartHandler(event) {
      this.touch.count += 1;
      if (this.touch.count > 1) {
        this.touch.multitouch = true;
      }
      this.touch.x = event.changedTouches[0].pageX;
      this.touch.y = event.changedTouches[0].pageY;
    },
    touchmoveHandler(event) {
      if (this.touch.flag || this.touch.multitouch) return;

      const touchEvent = event.touches[0] || event.changedTouches[0];

      if (touchEvent.pageX - this.touch.x > 40) {
        this.touch.flag = true;
        this.prev();
      } else if (touchEvent.pageX - this.touch.x < -40) {
        this.touch.flag = true;
        this.next();
      }
    },
    touchendHandler() {
      this.touch.count -= 1;
      if (this.touch.count <= 0) {
        this.touch.multitouch = false;
      }
      this.touch.flag = false;
    },
    keyDownHandler(event) {
      switch (event.keyCode) {
        case keyMap.LEFT:
          this.prev();
          break;
        case keyMap.RIGHT:
          this.next();
          break;
        case keyMap.ESC:
          this.close();
          break;
        default:
          break;
      }
    },
  },
};
</script>

<style lang="scss" scoped>
.light-gallery {
  &__modal {
    position: fixed;
    display: block;
    z-index: 1001;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
  }

  &__content {
    height: 100%;
    width: 100%;
    white-space: nowrap;
    padding: 0;
    margin: 0;
    overflow: hidden;
  }

  &__container {
    position: absolute;
    display: block;
    width: 100%;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }

  &__image {
    & {
      display: inline-table;
      vertical-align: middle;
      position: relative;
      width: 100%;
      height: 100%;
      text-align: center;
      transition: left .4s ease, transform .4s ease, -webkit-transform .4s ease;
    }

    img {
      display: block;
      margin: 0 auto;
      max-width: 100%;
    }
  }

  &__next,
  &__prev,
  &__close {
    position: absolute;
    z-index: 1002;
    display: block;
    background: transparent;
    border: 0;
    line-height: 0;
    outline: none;
    padding: 0;
    cursor: pointer;

    & svg {
      width: 44px;
      height: 60px;
    }
  }

  &__next {
    top: 50%;
    transform: translate(0, -50%);
    right: 1.5%;
    vertical-align: middle;
  }

  &__prev {
    top: 50%;
    transform: translate(0, -50%);
    left: 1.5%;
  }

  &__close {
    & {
      right: 0;
      padding: 20px;
    }

    svg {
      width: 30px;
      height: 30px;
    }
  }
}
.fade-enter-active, .fade-leave-active {
  position: fixed;
  z-index: 1000;
  transition: opacity .2s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
  position: fixed;
  opacity: 0;
  z-index: 1000;
}
</style>
