<template>
  <section class="c2-slider-component" :style="vars">
    <div
      class="c2-slider-wrapper"
      :class="[{ 'show-overflow': showOverflow }, sliderWrapperClasses]"
    >
      <div class="c2-slider" :style="translateStyle" :class="sliderClasses">
        <slot name="slide" />
      </div>
    </div>

    <nav v-if="!hideNavigation" aria-label="Slider Arrows" :class="navClasses">
      <div v-if="showIndicators" :class="indicatorClasses">
        {{ currentSlide }}
        <slot name="indicator-divider" />
        {{ totalSlides }}
      </div>

      <div
        v-if="showButtonNav && totalSlides > 0"
        :class="buttonNavWrapperClasses"
      >
        <button
          v-for="index in totalSlides"
          :key="index"
          @click="updateCurrentSlide(index)"
          :class="calcButtonClasses(index)"
          aria-label="Slide Selector"
        >
          <span class="sr-only">Move to slide {{ index }}</span>
        </button>
      </div>

      <button
        v-if="showNextPrevBtns"
        :class="prevBtnClasses"
        :disabled="disablePrevious"
        @click="prev"
        aria-label="Previous Slide Selector"
      >
        <slot name="prev-btn" />
      </button>

      <button
        v-if="showNextPrevBtns"
        :class="nextBtnClasses"
        :disabled="disableNext"
        @click="next"
        aria-label="Next Slide Selector"
      >
        <slot name="next-btn" />
      </button>
    </nav>
  </section>
</template>

<script>
export default {
  name: "C2Slider",
  props: {
    activeButtonClasses: {
      type: String,
      default: null,
    },
    buttonClasses: {
      type: String,
      default: null,
    },
    buttonNavWrapperClasses: {
      type: String,
      default: null,
    },
    showButtonNav: {
      type: Boolean,
      default: false,
    },
    showNextPrevBtns: {
      type: Boolean,
      default: true,
    },
    nextBtnClasses: {
      type: String,
      default: null,
    },
    prevBtnClasses: {
      type: String,
      default: null,
    },
    navClasses: {
      type: String,
      default: null,
    },
    indicatorClasses: {
      type: String,
      default: null,
    },
    slideSpeed: {
      type: Number,
      default: 300,
    },
    slidesToShow: {
      type: Number,
      default: 1,
    },
    slidesToShowMobile: {
      type: Number,
      default: null,
    },
    slidesToShowTablet: {
      type: Number,
      default: null,
    },
    gutter: {
      type: Number,
      default: 0,
    },
    showIndicators: {
      type: Boolean,
      default: true,
    },
    showOverflow: {
      type: Boolean,
      default: false,
    },
    mediaTabletQuery: {
      type: Number,
      default: 1023,
    },
    mediaMobileQuery: {
      type: Number,
      default: 639,
    },
    sliderWrapperClasses: {
      type: String,
      default: null,
    },
    sliderClasses: {
      type: String,
      default: null,
    },
    slideTotal: {
      type: Number,
      default: 0,
    },
  },
  data() {
    return {
      currentMedia: "desktop",
      currentSlide: 1,
      dataSlidesToShow: null,
      disableNext: true,
      disablePrevious: false,
      hideNavigation: false,
      index: this.slidesToShow,
      media: {
        tabletQuery: `(max-width: ${this.mediaTabletQuery}px)`,
        mobileQuery: `(max-width: ${this.mediaMobileQuery}px)`,
      },
      totalSlides: 0,
      translateValue: 0,
      vars: {},
      fullWidth: 100,
      minimumSlides: 2,
    };
  },
  computed: {
    translateStyle() {
      return {
        transform: `translateX(${this.translateValue}%)`,
      };
    },
  },
  watch: {
    currentMedia: function () {
      this.resetSlider();
    },
    hideNavigation: function () {
      this.checkForNavigation();
    },
    index: function (val) {
      this.checkForDisabledButtons(val);
    },
  },
  created() {
    if (!this.slidesToShowTablet && !this.slidesToShowMobile) {
      return;
    }
  },
  mounted() {
    const self = this;

    this.init();
    this.touchEvents();

    let windowWidth = window.innerWidth;

    window.addEventListener("resize", () => {
      // only check for width changes, mobile browsers change viewport
      // height on scroll when showing/hiding the navigation bar, and
      // we don't want to reset the slider every time that happens
      if (windowWidth !== window.innerWidth) {
        windowWidth = window.innerWidth;
        self.init();
      }
    });
  },
  methods: {
    calcButtonClasses(index) {
      if (index === this.currentSlide) {
        return `${this.buttonClasses} ${this.activeButtonClasses}`;
      } else {
        return this.buttonClasses;
      }
    },
    init() {
      this.getMedia();
      this.cssVars();
      this.calcTotalSlides();
      this.checkForNavigation();
      this.checkForDisabledButtons(this.index);
      this.currentSlide = 1;
    },
    // slideTotal () {
    //     let totalItems = 0;

    //     console.log(this);

    //     if (!this.$slots.slide) {
    //         return 0;
    //     } else {
    //         this.$slots.slide().forEach(item => {

    //             if (item.length > 0) {
    //                 totalItems += item.length;
    //             }
    //         });

    //         console.log(totalItems);
    //         console.log(this.minimumSlides);

    //         if (totalItems < this.minimumSlides) {
    //             this.hideNavigation = true;
    //         }
    //     }

    //     return totalItems;
    // },
    cssVars() {
      this.vars = {
        /* passing variable to scss */
        "--c2rowGutter": `-${Math.abs(this.gutter)}px`,
        "--c2SlideWidth": `${this.calcSlideWidth()}%`,
        "--c2SlideGutter": `${Math.abs(this.gutter)}px`,
        "--c2SlideSpeed": `${this.slideSpeed}ms`,
        "--c2SlideSliderWidth": `${this.calcSlideSliderWidth()}%`,
      };
    },
    calcTotalSlides() {
      this.totalSlides = Math.ceil(
        this.calcSlideSliderWidth() / this.fullWidth
      );
    },
    calcSlideWidth() {
      if (!this.$slots.slide) {
        return 0;
      }

      return this.fullWidth / this.slideTotal;
    },
    calcSlideSliderWidth() {
      const showAmount = this.fullWidth / this.dataSlidesToShow;
      return showAmount * this.slideTotal;
    },
    calcSlideTranslateWidth(direction) {
      const totalSlides = this.calcSlideSliderWidth() / this.fullWidth;
      const slideSetWidth = this.fullWidth / totalSlides;
      const slideSetRemainingWidth = (totalSlides % 1) * slideSetWidth;

      // hides nav if only one slides
      this.checkForNavigation();

      if (totalSlides % 1 === 0) {
        return slideSetWidth;
      }

      // returns different number if there is remaining space
      if (direction === "prev" && this.currentSlide + 1 > totalSlides) {
        return slideSetRemainingWidth;
      } else if (direction === "next" && this.currentSlide > totalSlides) {
        return slideSetRemainingWidth;
      }

      return slideSetWidth;
    },
    checkForDisabledButtons(val) {
      this.disablePrevious = val === this.dataSlidesToShow;
      this.disableNext = val >= this.slideTotal;
    },
    checkForNavigation() {
      this.hideNavigation = this.totalSlides < this.minimumSlides;
    },
    getMedia() {
      const self = this;

      if (window.matchMedia(self.media.mobileQuery).matches) {
        this.getMediaForMobile();
      } else if (window.matchMedia(self.media.tabletQuery).matches) {
        this.getMediaForTablet();
      } else {
        this.getMediaForDesktop();
      }
    },
    getMediaForDesktop() {
      this.currentMedia = "desktop";
      this.dataSlidesToShow = this.slidesToShow;
      this.index = this.slidesToShow;
    },
    getMediaForMobile() {
      this.currentMedia = "mobile";

      // provide fallback if mobile or tablet isn't provided
      if (!this.slidesToShowMobile && this.slidesToShowTablet) {
        this.getMediaForTablet();
        return;
      } else if (!this.slidesToShowMobile) {
        this.getMediaForDesktop();
        return;
      }

      this.dataSlidesToShow = this.slidesToShowMobile;
      this.index = this.slidesToShowMobile;
    },
    getMediaForTablet() {
      this.currentMedia = "tablet";

      // provide fallback if tablet isn't provided
      if (!this.slidesToShowTablet) {
        this.getMediaForDesktop();
        return;
      }

      this.dataSlidesToShow = this.slidesToShowTablet;
      this.index = this.slidesToShowTablet;
    },
    handleGesture(gesture) {
      let delta = {
        x: Math.abs(gesture.x.end - gesture.x.start),
        y: Math.abs(gesture.y.end - gesture.y.start),
      };
      // if this is a horizontal swipe
      if (delta.x > delta.y) {
        if (gesture.x.end < gesture.x.start) {
          this.next();
        }
        if (gesture.x.end >= gesture.x.start) {
          this.prev();
        }
      }
    },
    updateCurrentSlide(index) {
      let slidesToMove;
      let slideDir;

      if (this.currentSlide < index) {
        slideDir = "next";
        slidesToMove = index - this.currentSlide;
      } else if (this.currentSlide > index) {
        slideDir = "prev";
        slidesToMove = this.currentSlide - index;
      }

      if (slidesToMove && slideDir) {
        this.getTranslateValue(slidesToMove, slideDir);
      }
    },
    getTranslateValue(slidesToMove, slideDir) {
      let translateAmount = 0;

      for (let i = 0; i < slidesToMove; i++) {
        if (slideDir === "prev") {
          this.currentSlide--;
          translateAmount += this.calcSlideTranslateWidth("prev");
          this.index -= this.dataSlidesToShow;
        } else {
          this.currentSlide++;
          translateAmount += this.calcSlideTranslateWidth("next");
          this.index += this.dataSlidesToShow;
        }
      }

      if (slideDir === "prev") {
        this.translateValue += translateAmount;
      } else {
        this.translateValue -= translateAmount;
      }
    },
    next() {
      if (this.index >= this.slideTotal) {
        return;
      }

      this.currentSlide++;
      this.translateValue -= this.calcSlideTranslateWidth("next");
      this.index += this.dataSlidesToShow;
    },
    prev() {
      if (this.index <= this.dataSlidesToShow) {
        return;
      }

      this.currentSlide--;
      this.translateValue += this.calcSlideTranslateWidth("prev");
      this.index -= this.dataSlidesToShow;
    },
    resetSlider() {
      this.translateValue = 0;
      this.init();
    },
    touchEvents() {
      let gesture = {
        x: {
          start: 0,
          end: 0,
        },
        y: {
          start: 0,
          end: 0,
        },
      };

      this.$el.addEventListener(
        "touchstart",
        (event) => {
          gesture.x.start = event.changedTouches[0].screenX;
          gesture.y.start = event.changedTouches[0].screenY;
        },
        false
      );

      this.$el.addEventListener(
        "touchend",
        (event) => {
          gesture.x.end = event.changedTouches[0].screenX;
          gesture.y.end = event.changedTouches[0].screenY;
          this.handleGesture(gesture);
        },
        false
      );
    },
  },
};
</script>

<style lang="scss">
.c2-slider-component {
  touch-action: pan-y;
}

.c2-slider-wrapper {
  overflow: hidden;
  position: relative;
  margin: 0 var(--c2rowGutter);
  touch-action: pan-y;

  &.show-overflow {
    overflow: visible;
  }
}

.c2-slider {
  display: inline-flex;
  transition: var(--c2SlideSpeed) ease transform;
  width: var(--c2SlideSliderWidth);

  > div,
  > a {
    padding: 0 var(--c2SlideGutter);
    width: var(--c2SlideWidth);
  }
}
</style>
