<template>
  <div :class="[componentClass]" v-if="isComponentVisible">
    <div
      class="c-prev-btn c-btn"
      v-show="isBtnsVisible"
      @click="prev"
    >&#xe928;</div>
    <div
      class="c-next-btn c-btn"
      v-show="isBtnsVisible"
      @click="next"
    >&#xe927;</div>
    <div class="c-items c-progress" v-if="state === 0">
      <slot v-if="$scopedSlots.value" name="progress"></slot>
      <template v-else>
        <c-data-progress></c-data-progress>
      </template>
    </div>
    <div class="c-items c-errors" v-if="state === -1">
      <slot v-if="$scopedSlots.value" name="errors"></slot>
      <template v-else>
        <c-data-errors></c-data-errors>
      </template>
    </div>
    <div class="c-items" v-if="state === 1 && rowsCount > 0">
      <div
        v-if="hasValueSlot($scopedSlots, 'item')"
        class="c-items-container"
        :style="`${getTransition} ${getTransform}`"
        ref="itemsContainer"
      >
        <div
          class="c-item"
          v-for="(rowIndex, index) in getRowsIndex"
          :key="index"
          :class="[
            `index_${rowIndex}`,
            { 'currentRow': isCurrentRow(index-itemsToSlide) }
          ]"
          :style="{ width: `${getItemWidth}px` }"
        >
          <slot name="item" v-if="rows[rowIndex] != null" v-bind:row="rows[rowIndex]"></slot>
          <slot name="item-empty" v-else-if="hasValueSlot($scopedSlots, 'item-empty')"></slot>
        </div>
      </div>
      <div
        v-else
        class="c-items-container"
        :style="`${getTransition} ${getTransform}`"
        ref="itemsContainer"
      >
        <div
          class="c-item"
          v-for="(rowIndex, index) in getRowsIndex"
          :key="index"
          v-html="getTemplate(rowIndex)"
          :class="[
            `index_${rowIndex}`,
            { 'currentRow': isCurrentRow(index-itemsToSlide) }
          ]"
          :style="{ width: `${getItemWidth}px` }"
        />
      </div>
    </div>
    <div class="c-items c-empty" v-if="state === 1 && rowsCount === 0">
      <slot v-if="$scopedSlots.value" name="empty"></slot>
      <template v-else>
        <c-data-empty></c-data-empty>
      </template>
    </div>
    <div class="c-panel-navigation" v-if="isPanelNavVisible">
      <div
        v-for="rowIndex in rowsCount"
        :key="rowIndex-1"
        :class="{ 'c-active': isCurrentRow(rowIndex-1) }"
        @click="setSelectedRow(rowIndex-1)"
      />
    </div>
    <div class="c-panel-headers" v-if="isPanelHeaderVisibile">
      <div
        v-for="rowIndex in rowsCount"
        :key="rowIndex-1"
        :class="{ 'c-active': isCurrentRow(rowIndex-1) }"
        v-html="getHeader(rowIndex-1)"
        @click="setSelectedRow(rowIndex-1)"
      />
    </div>
  </div>
</template>

<script>
import base from "./c-base"
import { mapGetters, mapActions } from "vuex"

export default {
  extends: base,
  data: function() {
    return {
      componentClass: "c-carousel",
      watchTimeout: null,
      clientWidth: 0,
      isTransit: false,
      isTransitFromLastToFirst: false,
      isTransitFromFirstToLast: false
      // isTouch: false, unused
    }
  },
  props: {
    dataFieldTemplate: {
      type: String,
      default: null
    },
    dataFieldHeader: {
      type: String,
      default: null
    },
    dataFieldInterval: {
      type: String,
      default: null
    },
    itemsToShow: {
      type: Number,
      default: 1
    },
    itemsToSlide: {
      type: Number,
      default: 1
    },
    transitionTime: {
      type: Number,
      default: 300
    },
    showPanel: {
      type: Boolean,
      default: false
    },
    enableResize: {
      type: Boolean,
      default: true
    },
    hideWhenRowsCountLower: {
      type: Number,
      default: 0
    }
  },
  mounted: function() {
    this.$nextTick(() => {
      this.clientWidth = this.$el.clientWidth
    })
    window.addEventListener("resize", this.handleResize)
    this.start()
  },
  updated: function() {
    this.$nextTick(() => {
      this.clientWidth = this.$el.clientWidth
    })
    if (this.clientWidth !== this.$el.clientWidth)
      this.clientWidth = this.$el.clientWidth
    if (this.watchTimeout == null)
      this.start()
  },
  beforeDestroy: function() {
    window.removeEventListener("resize", this.handleResize)
  },
  computed: {
    ...mapGetters("csAppWindowsUtils", [
      "getDataSetCurrentRowIndex",
      "getDataSetRowsFieldValue"
    ]),
    isComponentVisible: function() {
      return this.state === 1 && !this.rowsIsEmpty && this.rowsCount > this.hideWhenRowsCountLower
    },
    isBtnsVisible: function() {
      return this.state === 1 && this.itemsToShow < this.rowsCount
    },
    isPanelNavVisible: function() {
      return this.state === 1 && this.showPanel && this.rowsCount > this.itemsToShow
    },
    isPanelHeaderVisibile: function() {
      return this.state === 1 && this.showPanel && this.rowsCount > this.itemsToShow && this.dataFieldHeader
    },
    getItemWidth: function() {
      return this.clientWidth / this.itemsToShow
    },
    currentRowIndex: function() {
      return this.getDataSetCurrentRowIndex(this.dataSet)
    },
    timeout: function() {
      return this.itemsToShow === this.rowsCount ? 0 : (this.getDataFieldValue(this.dataFieldInterval) || 0) * 1000
    },
    getTransition: function() {
      return this.isTransit ? `transition: all ${this.transitionTime}ms ease 0s;` : ''
    },
    getTransform: function() {
      let translateX
      if (this.itemsToShow === this.rowsCount) 
        translateX = 0 
      else
        translateX = (this.currentRowIndex + this.itemsToSlide) * this.getItemWidth
      if (this.isTransitFromLastToFirst)
        translateX = (this.currentRowIndex + this.rowsCount + this.itemsToSlide) * this.getItemWidth
      if (this.isTransitFromFirstToLast)
        translateX = (this.currentRowIndex + this.itemsToSlide - this.rowsCount) * this.getItemWidth
      return `transform: translate3d(-${translateX}px, 0px, 0px);`
    },
    getRowsIndex: function() {
      let result = []
      for (let i = 0; i < this.rowsCount; i++) {
        result.push(i)
      }
      if (this.itemsToShow === this.rowsCount) return result
      let toPush = 0
      if (this.rowsCount % this.itemsToShow > 0)
        for (let i = 0; i <= this.rowsCount % this.itemsToShow; i++) {
          result.push(toPush++)
        }
      let toUnshift = this.rowsCount - 1
      for (let i = 0; i < this.itemsToSlide; i++) {
        result.unshift(toUnshift)
        toUnshift = toUnshift - 1 < 0 ? this.rowsCount - 1 : toUnshift - 1
        result.push(toPush)
        toPush = toPush + 1 >= this.rowsCount ? 0 : toPush + 1
      }
      return result
    }
  },
  methods: {
    ...mapActions("csAppWindowsUtils", ["setDataSetCurrentRowIndex"]),
    hasValueSlot: function(scopedSlots, name) {
      return scopedSlots[name] ? true : false
    },
    handleResize: function() {
      if (this.enableResize)
        this.$nextTick(() => {
          this.clientWidth = this.$el.clientWidth
        })
    },
    startTransit: function() {
      clearTimeout(this.watchTimeout)
      this.isTransit = true
    },
    endTransit: function() {
      this.isTransit = false
      this.isTransitFromLastToFirst = false
      this.isTransitFromFirstToLast = false
      this.start()
    },
    transitToRow: function(rowIndex) {
      this.setDataSetCurrentRowIndex({
        appWindowIdent: this.appWindowIdent,
        dataSet: this.dataSet,
        currentRowIndex: rowIndex
      })
      this.startTransit()
      setTimeout(() => {
        this.endTransit()
      }, this.transitionTime)
    },
    next: function() {
      if (this.isTransit) return 
      let newCurrentRowIndex = this.currentRowIndex + this.itemsToSlide
      if (newCurrentRowIndex >= this.rowsCount) {
        newCurrentRowIndex -= this.rowsCount
        this.isTransitFromLastToFirst = true
      }
      else { 
        newCurrentRowIndex = this.currentRowIndex + this.itemsToSlide
      }
      this.transitToRow(newCurrentRowIndex)
    },
    prev: function() {
      if (this.isTransit) return
      let newCurrentRowIndex = this.currentRowIndex - this.itemsToSlide
      if (newCurrentRowIndex < 0) {
        newCurrentRowIndex = this.rowsCount + newCurrentRowIndex
        this.isTransitFromFirstToLast = true
      }
      else { 
        newCurrentRowIndex = this.currentRowIndex - this.itemsToSlide
      }
      this.transitToRow(newCurrentRowIndex)
    },
    setSelectedRow: function(rowIndex) {
      if (this.isTransit) return
      this.transitToRow(rowIndex)
    },
    isCurrentRow: function(rowIndex) {
      return rowIndex === this.currentRowIndex
    },
    getTemplate: function(rowIndex) {
      return this.dataFieldTemplate ? this.getDataSetRowsFieldValue(this.dataSet, this.dataFieldTemplate, this.rows[rowIndex]) : null
    },
    getHeader: function(rowIndex) {
      return this.dataFieldHeader ? this.getDataSetRowsFieldValue(this.dataSet, this.dataFieldHeader, this.rows[rowIndex]): null
    },
    start: function() {
      if(this.timeout <= 0) return
      this.watchTimeout = setTimeout(() => {
        this.next()
      }, this.timeout)
    }
  },
  watch: {
    itemsToShow: function() {
      this.clientWidth = this.$el.clientWidth
    }
  }
}
</script>
