import $ from 'jquery';
import Hammer from 'hammerjs';

import 'jquery.easing';

class IHKSlider {
  constructor(section) {
    this.section = section.addClass('initiated');
    this.slides = section.children();
    this.slideOverflow = $('<div class="slide-overflow" />').appendTo(section);
    this.slideWrapper = $('<div class="slide-wrapper" />').appendTo(this.slideOverflow).append(this.slides);
    this.currentSlide = 0;
    this.autoplayTimeout = 0;
    this.isHovered = false;
    this.sectionInitialClicked = false;
    this.dragging = false;
    this.inViewport = false;
    this.positionAnimation = {
      x: 0
    }
    this.settings = {
      loop: false,
      autoplay: this.section.data('autoplay'),
      infinite: true,
      autoplaySpeed: this.section.data('autoplay-speed') ? this.section.data('autoplay-speed') : 5000,
      animationSpeed: 600,
      startSlide: 0
    };

    this.initSlides();
    if (this.settings.infinite) {
      this.initInfinity();
    }
    this.initUI();
    this.checkSize();

    if (this.slides.length > 1) {
      this.initHammerDragging();
      this.initTabbing();
    }

    this.changeSlide(this.settings.startSlide);
    this.initAutoplay();
    this.checkSize();

    if (this.section.closest('.steps').length) {
      this.setupSteps();
    }

    $(window).on('resize', () => {
      this.checkSize();
    })
  }

  initSlides() {
    this.slides.each(function (i) {
      const slide = $(this).attr('data-index', i);
      const h3 = slide.find('h3, .like-h2, .like-h3').first();
      const p = h3.next('p');
      const dotsString = '&hellip;'

      if (!slide.find('.image-box img').length) {
        slide.addClass('text-only');
      } else {
        if (h3.text().length > 48) {
          h3.html(h3.text().substring(0, 48) + dotsString);
        }
        if (p.text().length > 148) {
          p.html(p.text().substring(0, 148) + dotsString);
        }
      }
    })
  }

  checkSize() {
    if (this.controls.find('.tabs').width() > this.slideOverflow.width() * 0.6) {
      this.section.addClass('many-slides');
    } else {
      this.section.removeClass('many-slides');
    }
  }

  initInfinity() {
    this.nextWrapper = this.slideWrapper.clone();
    this.prevWrapper = this.slideWrapper.clone();

    this.nextWrapper
      .removeClass('slide-wrapper')
      .addClass('next-clone')
      .appendTo(this.slideWrapper)
      .css({'left': this.slides.length + '%'});
    this.prevWrapper
      .removeClass('slide-wrapper')
      .addClass('prev-clone')
      .appendTo(this.slideWrapper);

    this.nextWrapper.find('a, button, input, select, textarea').attr('tabindex', -1);
    this.prevWrapper.find('a, button, input, select, textarea').attr('tabindex', -1);

    this.nextWrapper.find('img').removeClass('loading');
    this.prevWrapper.find('img').removeClass('loading');
  }

  initUI() {
    this.count = $('<span />');

    this.prevButton = $('<button class="prev" aria-label="Zurück" />');
    this.nextButton = $('<button class="next" aria-label="Weiter" />');
    const tabsWrapper = $('<ul class="slider-tabs variant-base" />');
    const countWrapper = $('<span class="count" />')
      .html('/<span class="total">' + this.slides.length + '</span></span>')
      .prepend(this.count);

    this.tabs = tabsWrapper.children();

    if (this.slides.length > 1) {
      this.slides.each(function (i) {
        const s = $(this);
        const li = $('<li/>').appendTo(tabsWrapper);

        var button = $('<button />').addClass('btn').appendTo(li);
        const span = $('<span/>').appendTo(button);

        span.text(s.data('title') ? s.data('title') : i + 1);
      });
      this.tabs = tabsWrapper.children();

      tabsWrapper.find('button').on('click', (e) => {
        e.preventDefault();
        this.sectionInitialClicked = true;
        this.changeSlide($(e.currentTarget).parent().index());
      });

      this.prevButton.on('click', (e) => {
        e.preventDefault();
        this.sectionInitialClicked = true;
        this.onPrev();
      });

      this.nextButton.on('click', (e) => {
        e.preventDefault();
        this.sectionInitialClicked = true;
        this.onNext();
      });

      this.controls = $('<div class="controls" />')
        .append(this.prevButton)
        .append(tabsWrapper)
        .append(countWrapper)
        .append(this.nextButton)
        .appendTo(this.section);
    } else {
      this.controls = $('<div class="controls" />')
        .append(countWrapper)
        .appendTo(this.section);
    }
  }

  changeSlide(index, offset, transition = true) {
    const t = this;
    const prevIndex = index === 0 ? this.slides.length - 1 : index - 1;
    const nextIndex = index === this.slides.length - 1 ? 0 : index + 1;
    const allWidth = this.settings.infinite
        ? this.slideWrapper.width() * this.slides.length
        : 0;

    if (!offset) {
      offset = 0;
    }
    if (index === this.currentSlide && this.slideOverflow.outerHeight() === 0) {
      transition = false;
    }

    t.positionAnimation = {
      x: this.slideWrapper.position()?.left ?? 0
    }

    let target = (index + offset) / -100 * this.slideWrapper.width();
    let time = Math.round(Math.abs(this.positionAnimation.x - target) / 5 + 200);

    if (time > 500) {
      time = 500;
    }
    if (!transition) {
      time = 0;
    }

    t.slideOverflow.css({
      'transition-duration': time + 'ms', 'height': this.slideOverflow.outerHeight() + 'px'
    });

    t.slideWrapper.find('.current').removeClass('current');
    t.slideWrapper.find('[data-index="' + index + '"]').addClass('current');

    t.slideWrapper.find('.is-prev').removeClass('is-prev');
    t.slideWrapper.find('[data-index="' + prevIndex + '"]').addClass('is-prev');

    t.slideWrapper.find('.is-next').removeClass('is-next');
    t.slideWrapper.find('[data-index="' + nextIndex + '"]').addClass('is-next');

    if (target > 0) {
      target = target - allWidth;
      this.positionAnimation.x = this.positionAnimation.x - allWidth;
    }
    if (target <= allWidth * -1 + 1) {
      target = target + allWidth;
      this.positionAnimation.x = this.positionAnimation.x + allWidth;
    }

    requestAnimationFrame(() => {
      this.slideOverflow.css({
        'height': this.slides.eq(index).outerHeight() + 'px'
      });
    })

    $(this.positionAnimation).animate({
      x: target
    }, {
      duration: time, easing: 'easeOutCubic', step: (now) => {
        this.slideWrapper.css({'transform': 'translate3d(' + Math.round(now) + 'px, 0, 0)'});
      }, complete: () => {
        requestAnimationFrame(() => {
          this.slideWrapper.css({'transform': 'translate3d(' + (index * -1) + '%, 0, 0)'});
          this.slideOverflow.css('height', 'auto');
        });
      }
    })

    this.tabs.eq(index).addClass('active').siblings('.active').removeClass('active');
    this.count.text(index + 1);

    if (this.settings.autoplay && !this.isHovered) {
      this.handleAutoplay();
    }

    if (offset !== 0) {
      setTimeout(() => {
        this.slideWrapper.addClass('no-transition');
        this.slideWrapper.css({'transform': 'translate3d(' + (index * -1) + '%, 0, 0)'});
        setTimeout(() => {
          this.slideWrapper.removeClass('no-transition');
        }, 20);
      }, this.settings.animationSpeed);
    }

    this.currentSlide = index;
    this.section.trigger('slide-change');

    if (this.section.closest('.steps').length && this.sectionInitialClicked) {
      this.scrollToTop();
    }
  }

  goTo(index, transition) {
    if (transition === false) {
      this.slideWrapper.addClass('no-transition');
    }
    this.sectionInitialClicked = true;
    this.changeSlide(index, 0, transition);

    setTimeout(() => {
      this.slideWrapper.removeClass('no-transition');
    }, 20);
  }

  onNext() {
    const nextSlide = this.currentSlide === this.slides.length - 1 ? 0 : this.currentSlide + 1;
    const offset = this.settings.infinite && nextSlide === 0 ? this.slides.length : 0;

    this.changeSlide(nextSlide, offset);
  }

  onPrev() {
    const prevSlide = this.currentSlide === 0 ? this.slides.length - 1 : this.currentSlide - 1;
    const offset = this.settings.infinite && prevSlide === this.slides.length - 1 ? this.slides.length * -1 : 0;

    this.changeSlide(prevSlide, offset);
  }

  initAutoplay() {
    this.section.on('mouseenter', () => {
      this.isHovered = true;
      clearTimeout(this.autoplayTimeout);
      this.section.removeClass("btnanimation");
    })
    this.section.on('mouseleave', () => {
      this.isHovered = false;
      this.handleAutoplay();
      this.section.addClass("btnanimation");
    })

    this.initScrollCheck();
    this.handleAutoplay();
  }

  handleAutoplay() {
    if (this.dragging) {
      return false;
    }

    clearTimeout(this.autoplayTimeout);

    if (this.settings.autoplaySpeed > 0 && this.settings.autoplay) {
      this.autoplayTimeout = setTimeout(() => {
        if (this.inViewport) {
          this.onNext();
        } else {
          this.handleAutoplay();
        }
      }, this.settings.autoplaySpeed);
    }
  }

  initScrollCheck() {
    window.addEventListener("scroll", () => {
      window.requestAnimationFrame(() => {
        this.scrollCheck();
      })
    }, {passive: true});

    window.requestAnimationFrame(() => {
      this.scrollCheck();
    })
  }

  scrollCheck() {
    const w = $(window);
    const offset = this.section.offset();

    if (!offset) return;

    if (w.scrollTop() + w.height() - 200 > this.section.offset().top && w.scrollTop() < this.section.offset().top + this.section.outerHeight() / 2) {
      if (!this.inViewport) {
        this.inViewport = true;
        this.section.addClass('in-viewport').trigger('in-viewport');
      }
    } else if (this.inViewport) {
      this.inViewport = false;
      this.section.removeClass('in-viewport');
    }
  }

  initHammerDragging() {
    const hammer = new Hammer(this.slideWrapper.get(0));

    let sliderWidth = 0;
    let startValue = 0;

    this.dragging = false;
    this.slideWrapper.find('img, a').attr('draggable', 'false').attr('ondragstart', 'return false;');

    hammer.on('panstart', (e) => {
      sliderWidth = this.slideOverflow.width();
      // Disable click on drag
      this.slideWrapper.find('a').css('pointer-events', 'none');

      this.dragging = true;
      startValue = this.slideWrapper.position().left;

      $(this.positionAnimation).stop();

      requestAnimationFrame(() => {
        $('html').addClass('slider-dragging');
      })

      if (e.center.x !== 0 && e.center.y !== 0) {
        clearTimeout(this.autoplayTimeout);
      }
    });

    hammer.on('pan', (e) => {
      if (e.center.x !== 0 && e.center.y !== 0) {
        const transformX = Math.round(startValue + e.deltaX);
        this.slideWrapper.css({'transform': 'translate3d(' + transformX + 'px, 0, 0)'});
      }
    });

    hammer.on('panend', (e) => {
      this.slideWrapper.find('a').addClass('dragging');
      this.dragging = false;

      requestAnimationFrame(() => {
        $('html').removeClass('slider-dragging');
        if (e.deltaX > sliderWidth / 5) {
          this.onPrev();
        } else if (e.deltaX < sliderWidth / -5) {
          this.onNext();
        } else {
          this.changeSlide(this.currentSlide);
        }
      });
      // Enable click on drag
      this.slideWrapper.find('a').css('pointer-events', 'all');
    });
  }

  initTabbing() {
    $(window).keydown((e) => {
      const code = (e.keyCode ? e.keyCode : e.which);
      if (code === 9 && this.slideWrapper.find(':focus').length) {
        this.tabScrollActive = true;
        this.resetTabScroll();
      }
    })

    $(window).keyup((e) => {
      const code = (e.keyCode ? e.keyCode : e.which);
      if (code === 9 && this.slideWrapper.find(':focus').length) {
        const slide = this.section.find(':focus').closest('.slide');
        this.slideOverflow.scrollLeft(0).scrollTop(0).find('.outer, .text-box').scrollLeft(0).scrollTop(0);
        this.goTo(parseInt(slide.attr('data-index')), true);
        this.tabScrollActive = false;
      }
    });
  }

  loadImage(index) {
    const t = this;

    if (!index) {
      index = this.currentSlide;
    }

    if (t.slides.eq(index).hasClass('preload') && !t.slides.eq(index).find('img').length) {
      const ib = t.slides.eq(index).find('.image-box');
      const img = $('<img/>').one('load', function (e) {
        const loadedImage = $(this).removeClass('loading');
        const slide = loadedImage.closest('.slide').removeClass('preload');
        const index = parseInt(slide.attr('data-index'));

        const nextItem = t.nextWrapper.find('[data-index="' + index + '"]').removeClass('preload').find('.image-box');
        nextItem.append(loadedImage.clone());
        nextItem.find('img').attr('alt', ib.attr('data-alt') || '');
        // Copyright für Next-Wrapper
        if (ib.attr('data-copyright')) {
          $('<span class="copyright" aria-hidden="true">').html(ib.attr('data-copyright')).appendTo(nextItem);
          $('<span class="sr-only">').html(ib.attr('data-copyright')).appendTo(nextItem);
        }
        const prevItem = t.prevWrapper.find('[data-index="' + index + '"]').removeClass('preload').find('.image-box');
        prevItem.append(loadedImage.clone());
        prevItem.find('img').attr('alt', ib.attr('data-alt') || '');
        // Copyright für Prev-Wrapper
        if (ib.attr('data-copyright')) {
          $('<span class="copyright">').html(ib.attr('data-copyright')).appendTo(prevItem);
        }

        //t.nextWrapper.find('[data-index="' + index + '"]').removeClass('preload').find('.image-box').append(loadedImage.clone());
        //t.prevWrapper.find('[data-index="' + index + '"]').removeClass('preload').find('.image-box').append(loadedImage.clone());
      });

      img.attr('src', ib.attr('data-src')).attr('alt', ib.attr('data-alt') || '').appendTo(ib);
      img.attr('data-download', ib.attr('data-download'));
      img.attr('draggable', 'false').attr('ondragstart', 'return false;');

      // Copyright für das Hauptbild hinzufügen
      if (ib.attr('data-copyright')) {
        $('<span class="copyright">').html(ib.attr('data-copyright')).appendTo(ib);
      }
    }
  }

  resetTabScroll() {
    this.slideOverflow.scrollLeft(0).scrollTop(0).find('.outer, .text-box').scrollLeft(0).scrollTop(0);

    if (this.tabScrollActive) {
      window.requestAnimationFrame(() => {
        this.resetTabScroll();
      })
    }
  }

  scrollToTop() {
    const target = this.section.closest('.steps').offset().top - 120;
    const time = 600;

    $('html, body').animate({'scrollTop': target}, time, 'easeOutQuad');
  };

  setupSteps() {
    this.nextButton.text('Weiter').addClass('btn').addClass('has-icon').addClass('icon-right').addClass('icon-pfeil-rechts');
  }
}

export default IHKSlider;

$('body').on('ihk-init dynamic-component-loaded gfi-dynamic-init', () => {
  $('.rotation .slider:not(.initiated), .steps .slider:not(.initiated)').each((i, el) => {
    const selector = $(el);
    if (!selector.find('dynamic-content').length) {
      new IHKSlider(selector);
    }
  })
  /*
  let slidersSelector;
  if (e.type === "ihk-init") {
    slidersSelector = $('.rotation .slider:not(.initiated):not(:has(dynamic-content)), .steps .slider:not(.initiated):not(:has(dynamic-content))')
  } else {
    slidersSelector = $('.rotation .slider:not(.initiated), .steps .slider:not(.initiated)');
  }
  slidersSelector.each(function () {
    new Slider($(this));
  });
  */
});
