<template>
  <div
    v-bind:class="[componentClass]"
    v-if="state === 1 && !rowsIsEmpty && rowsCount > hideWhenRowsCountLower"
  >
    <div
      class="c-prev-btn c-btn"
      v-show="state === 1 && itemsToShowComp < pageRowsCount"
      @click="prevRow"
    >&#xe928;</div>
    <div
      class="c-next-btn c-btn"
      v-show="state === 1 && itemsToShowComp < pageRowsCount"
      @click="nextRow"
    >&#xe927;</div>
    <div class="c-items" v-if="state === 0" v-bind:class="[{ 'c-progress': true }]">
      <slot v-if="$scopedSlots.value" name="progress"></slot>
      <template v-else>
        <c-data-progress></c-data-progress>
      </template>
    </div>
    <div class="c-items" v-if="state === -1" v-bind:class="[{ 'c-errors': true }]">
      <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 && pageRowsCount !== 0">
      <div
        v-if="hasValueSlot($scopedSlots, 'item')"
        class="c-items-container"
        :style="trackTransform + trackTransition"
        ref="itemsContainer"
      >
        <div
          class="c-item"
          v-for="(row, rowIndex) in virtualpageRowsCount"
          :key="getRowKey(rowIndex)"
          v-bind:class="[
            'index_' + getRowKey(rowIndex),
            isCurrentRow(rowIndex) ? 'currentRow' : null
          ]"
          :style="{ width: itemWidthComp + 'px' }"
        >
          <slot name="item" v-if="rows[getRowIndex(rowIndex)] != null" v-bind:row="rows[getRowIndex(rowIndex)]"></slot>
          <slot name="item-empty" v-else-if="hasValueSlot($scopedSlots, 'item-empty')"></slot>
        </div>
      </div>
      <div
        v-else
        class="c-items-container"
        :style="trackTransform + trackTransition"
        ref="itemsContainer"
      >
        <div
          class="c-item"
          v-for="(row, rowIndex) in virtualpageRowsCount"
          :key="getRowKey(rowIndex)"
          v-html="getTemplate(rowIndex)"
          v-bind:class="[
            'index_' + getRowKey(rowIndex),
            isCurrentRow(rowIndex) ? 'currentRow' : null
          ]"
          :style="{ width: itemWidthComp + 'px' }"
        ></div>
      </div>
    </div>
    <div
      class="c-items"
      v-if="state === 1 && pageRowsCount === 0"
      v-bind:class="[{ 'c-empty': true }]"
    >
      <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="pageRowsCount > itemsToShowComp && showPanel">
      <div
        v-for="(row, rowIndex) in pageRowsCount"
        :key="rowIndex"
        v-bind:class="[rowIndex === currentRowIndex ? 'c-active' : null]"
        @click="setCurrentRow(rowIndex)"
      />
    </div>
    <div class="c-panel-headers" v-if="dataFieldHeader && showPanel">
      <div
        v-for="(header, rowIndex) in getHeaders"
        :key="rowIndex"
        v-bind:class="[rowIndex === currentRowIndex ? 'c-active' : null]"
        @click="setCurrentRow(rowIndex)"
      >
        {{ header }}
      </div>
    </div>
  </div>
</template>
<script>
import base from "./c-base";
import { mapGetters, mapActions } from "vuex";

export default {
  extends: base,
  data: function() {
    return {
      componentClass: "c-html-content-panel",
      watchLock: false,
      watchTimeout: null,
      shiftCounter: 0,
      clientWidth: 0,
      isSliding: false,
      isTouch: false,
      direction: 1,
      shift: 1
    };
  },
  props: {
    dataFieldTemplate: {
      type: String,
      default: null
    },
    dataFieldHeader: {
      type: String,
      default: null
    },
    dataFieldInterval: {
      type: String,
      default: null
    },
    itemsToShow: {
      type: Number,
      default: 1
    },
    itemsToSlide: {
      default: 1,
      type: Number
    },
    transitionTime: {
      default: 300,
      type: Number
    },
    showPanel: {
      default: false,
      type: Boolean
    },
    enableResize: {
      default: true,
      type: Boolean
    },
    hideWhenRowsCountLower: {
      type: Number,
      default: -1
    }
  },
  mounted: function() {
    this.shift = this.itemsToSlide;
    this.setTimeoutToSlide();
    this.$nextTick(() => {
      this.clientWidth = this.$el.clientWidth;
    });
    window.addEventListener("resize", this.handleResize);
  },
  updated: function() {
    this.$nextTick(() => {
      this.clientWidth = this.$el.clientWidth;
    });
    if (this.watchTimeout == null)
      this.setTimeoutToSlide()
    if (this.clientWidth !== this.$el.clientWidth)
      this.clientWidth = this.$el.clientWidth;
    if (this.shift !== this.itemsToSlide)
      this.shift = this.itemsToSlide;
  },
  beforeDestroy: function() {
    window.removeEventListener("resize", this.handleResize);
  },
  computed: {
    ...mapGetters("csAppWindowsUtils", [
      "getDataSetCurrentRowIndex",
      "getDataSetRowsFieldValue"
    ]),
    pageRowsCount: function() {
      return this.rows.length
    },
    itemsToShowComp: function() {
      return this.itemsToShow
    },
    itemWidthComp: function() {
      return this.clientWidth / this.itemsToShowComp;
    },
    currentRowIndex: function() {
      return this.getDataSetCurrentRowIndex(this.dataSet);
    },
    payload: function() {
      return {
        dataSet: this.dataSet,
        step: this.itemsToSlide
      };
    },
    timeout: function() {
      return (this.getDataFieldValue(this.dataFieldInterval) || 0) * 1000;
    },
    virtualpageRowsCount: function() {
      return this.itemsToShowComp + this.additionalRowsCount;
    },
    additionalRowsCount: function() {
      return this.showPanel && this.pageRowsCount > 3 * this.itemsToSlide
        ? 2 * this.pageRowsCount
        : (this.pageRowsCount <= this.itemsToShowComp ? 0 : 4) *
            this.itemsToSlide;
    },
    trackTransition: function() {
      if (this.isSliding) {
        return `transition: ${this.transitionTime}ms;`;
      }
      return "";
    },
    trackTransform: function() {
      if (this.pageRowsCount <= this.itemsToShowComp) return "";
      if (this.isSliding) {
        return `transform: translate(${(-this.additionalRowsCount / 2) *
          this.itemWidthComp -
          this.shift * this.direction * this.itemWidthComp}px, 0px);`;
      }
      return `transform: translate(${(-this.additionalRowsCount / 2) *
        this.itemWidthComp}px, 0px);`;
    },
    getHeaders: function() {
      let headers = [];
      this.rows.forEach(row => {
        headers.push(this.getDataSetRowsFieldValue(
          this.dataSet,
          this.dataFieldHeader,
          row
        ));
      })
      return headers;
    }
  },
  methods: {
    ...mapActions("csAppWindowsUtils", ["setDataSetCurrentRowIndex"]),
    handleResize: function() {
      if (this.enableResize)
        this.$nextTick(() => {
          this.clientWidth = this.$el.clientWidth;
        });
    },
    startSliding: function() {
      if (this.watchTimeout !== null) clearTimeout(this.watchTimeout);
      this.watchLock = false;
      this.isSliding = true;
    },
    endSliding: function() {
      this.isSliding = false;
      this.direction = 1;
    },
    nextRow: function() {
      if (this.isSliding) return;
      this.direction = 1;
      this.startSliding();
      setTimeout(() => {
        this.shiftCounter += this.itemsToSlide;
        this.endSliding();
      }, this.transitionTime);
    },
    hasValueSlot: function(scopedSlots, name) {
      return scopedSlots[name] ? true : false;
    },
    prevRow: function() {
      if (this.isSliding) return;
      this.direction = -1;
      this.startSliding();
      setTimeout(() => {
        this.shiftCounter -= this.itemsToSlide;
        this.endSliding();
      }, this.transitionTime);
    },
    getRowIndex: function(rowIndex) {
      if (this.pageRowsCount <= this.itemsToShowComp) return rowIndex;
      let shiftTemp = this.shiftCounter % this.pageRowsCount;
      if (shiftTemp < 0) shiftTemp = this.pageRowsCount + shiftTemp;
      return (
        (rowIndex -
          this.additionalRowsCount / 2 +
          shiftTemp +
          this.pageRowsCount) %
        this.pageRowsCount
      );
    },
    isCurrentRow: function(rowIndex) {
      let index = this.getRowIndex(rowIndex)
      return index === this.currentRowIndex
    },
    getTemplate: function(rowIndex) {
      let index = this.getRowIndex(rowIndex);
      if (index >= this.pageRowsCount || !this.dataFieldTemplate) return null;
      return this.getDataSetRowsFieldValue(
        this.dataSet,
        this.dataFieldTemplate,
        this.rows[this.getRowIndex(rowIndex)]
      );
    },
    setTimeoutToSlide: function() {
      if (!this.watchLock && this.timeout > 0) {
        this.watchLock = true;
        this.watchTimeout = setTimeout(() => {
          this.nextRow();
        }, this.timeout);
      }
    },
    getRowKey: function(rowIndex) {
      let shiftTemp = this.shiftCounter % this.virtualpageRowsCount;
      if (shiftTemp < 0) shiftTemp = this.virtualpageRowsCount + shiftTemp;
      return (shiftTemp + rowIndex) % this.virtualpageRowsCount;
    },
    setCurrentRow: function(rowIndex) {
      if (this.isSliding) return;
      let shift = rowIndex - this.currentRowIndex;
      this.direction = shift > 0 ? 1 : -1;
      this.shift = Math.abs(shift);
      this.startSliding();
      setTimeout(() => {
        this.shiftCounter += shift;
        this.endSliding();
        this.shift = this.itemsToSlide;
      }, this.transitionTime);
    }
  },
  watch: {
    shiftCounter: function(newShiftCounter) {
      this.setTimeoutToSlide();
      let shiftTemp = newShiftCounter % this.pageRowsCount;
      if (shiftTemp < 0) shiftTemp = this.pageRowsCount + shiftTemp;
      let currentRowIndex =
        (shiftTemp + this.pageRowsCount) % this.pageRowsCount;
      let payload = {
        appWindowIdent: this.appWindowIdent,
        dataSet: this.dataSet,
        currentRowIndex: currentRowIndex
      };
      this.setDataSetCurrentRowIndex(payload);
    },
    itemsToShow: function() {
      this.clientWidth = this.$el.clientWidth;
    }
  }
};
</script>
