/**
 * carousel.js
 * Script to create carousel components
 */

import ElementHelpers from '../helpers/element-helpers';
import $ from 'jquery';
import 'slick-carousel';

/**
 * Declare constants
 */
const attributeBase = 'data-rs-carousel';

export class Carousel {
  constructor(element) {
    this.element = element;
    this.variant = element.getAttribute(attributeBase);
    this.slides = ElementHelpers.getElementsByAttributeWithinElement(
      this.element,
      this.attributes.slide
    );
    this.buttonId = element.getAttribute(this.attributes.buttonId);
    this.addEventHandlers();
    this.initializeCarousel();
  }

  /**
   * Add event handlers
   */
  addEventHandlers() {
    window.addEventListener('resize', () => {
      this.initializeCarousel();
    });
  }

  /**
   * Declare attribute constants
   */
  get attributes() {
    return {
      buttonId: `${attributeBase}-button-id`,
      cards: 'cards',
      dotsColor: `${attributeBase}-dots-color`,
      dotsHeight: `${attributeBase}-dots-height`,
      image: `${attributeBase}-image`,
      slide: `${attributeBase}-slide`,
      textColor: `${attributeBase}-text-color`,
      wrapper: `${attributeBase}-wrapper`
    };
  }

  /**
   * Declare variants
   */
  get variants() {
    return {
      applicationProcess: 'application-process',
      blogOverviewCarousel: 'blog-overview--carousel',
      blogOverviewGrid: 'blog-overview--grid',
      blogOverviewTopic: 'blog-overview--topic',
      cards: 'cards',
      photo: 'photo',
      quote: 'quote'
    };
  }

  /**
   * Declare classes
   */
  get classes() {
    return {
      slickArrow: 'slick-arrow',
      slickInitialized: 'slick-initialized',
      slickNext: 'slick-next',
      slickPrev: 'slick-prev',
      slickDots: 'slick-dots',
      hidden: 'hidden',
      dark: 'dark',
      textDark: 'text--dark-from-l'
    };
  }

  /**
   * Initialize carousel
   */
  initializeCarousel() {
    let defaultSlickOptions = {
      arrows: false,
      infinite: false,
      slidesToShow: 1,
      slidesToScroll: 1,
      mobileFirst: true,
      swipeToSlide: true,
      responsive: [
        {
          breakpoint: ElementHelpers.maxWidthMobileViewports(),
          settings: {
            appendArrows: $(this.element).parents(
              `[${this.attributes.wrapper}]`
            ),
            arrows: true,
            draggable: false,
            slidesToShow: 3,
            slidesToScroll: 1
          }
        }
      ]
    };

    if (!this.element.classList.contains(this.classes.slickInitialized)) {
      this.removeHiddenClass();

      const initSlick = () => $(this.element).slick(defaultSlickOptions);
      const _this = this;

      switch (this.variant) {
        case this.variants.blogOverviewCarousel:
          defaultSlickOptions.responsive[0].settings.slidesToShow = 2;
          initSlick();
          break;

        case this.variants.blogOverviewGrid:
          defaultSlickOptions.responsive[0].settings = 'unslick';
          initSlick();
          break;

        case this.variants.blogOverviewTopic:
          initSlick();
          break;

        case this.variants.applicationProcess:
          defaultSlickOptions.responsive[0].settings.slidesToShow = 1;
          initSlick();
          break;

        case this.variants.photo: {
          this.sliderDots = this.element.nextElementSibling;
          defaultSlickOptions.dots = true;
          defaultSlickOptions.appendDots = this.sliderDots;
          defaultSlickOptions.responsive = [
            {
              breakpoint: ElementHelpers.maxWidthMobileViewports(),
              settings: {
                swipe: false
              }
            }
          ];

          if (!this.sliderDots) {
            return;
          }

          $(this.element).on(
            'beforeChange',
            function (event, slick, currentSlide, nextSlide) {
              if (!slickDots) {
                return;
              }

              const currentSlideEl = slides[nextSlide];

              const textColor = currentSlideEl.getAttribute(
                _this.attributes.textColor
              );

              slickDots.classList.remove(
                'slick-dots--dark',
                'slick-dots--light'
              );

              if (textColor === 'dark') {
                slickDots.classList.add('slick-dots--dark');
              } else {
                slickDots.classList.add('slick-dots--light');
              }
            }
          );

          initSlick();

          const slickDots = ElementHelpers.getElementByClassWithinElement(
            this.sliderDots,
            this.classes.slickDots
          );

          if (!slickDots) {
            return;
          }

          const slides = this.slides;
          const firstSlide = slides[0];

          const textColorFirstSlide = firstSlide.getAttribute(
            this.attributes.textColor
          );

          if (textColorFirstSlide === 'dark') {
            slickDots.classList.add('slick-dots--dark');
          } else {
            slickDots.classList.add('slick-dots--light');
          }

          break;
        }

        case this.variants.quote:
          defaultSlickOptions.dots = true;
          defaultSlickOptions.responsive = [
            {
              breakpoint: ElementHelpers.maxWidthMobileViewports(),
              settings: {
                swipe: false
              }
            }
          ];
          initSlick();
          break;

        case this.variants.cards:
          defaultSlickOptions.responsive[0].settings = 'unslick';
          initSlick();
          break;

        default:
          return;
      }
    }

    //if slider is carousel/topic/applicationprocess, set arrow heights equal to images in slider on resize window
    if (
      this.variant === this.variants.blogOverviewCarousel ||
      this.variants.blogOverviewTopic ||
      this.variants.applicationProcess
    ) {
      const slickArrowNextButton = this.element.parentElement.querySelector(
        `.${this.classes.slickNext}.${this.classes.slickArrow}`
      );
      const slickArrowPrevButton = this.element.parentElement.querySelector(
        `.${this.classes.slickPrev}.${this.classes.slickArrow}`
      );
      const image = ElementHelpers.getElementByAttributeWithinElement(
        this.element,
        this.attributes.image
      );
      if (
        slickArrowNextButton !== null &&
        slickArrowPrevButton !== null &&
        image !== null
      ) {
        if (this.buttonId) {
          slickArrowNextButton.id = `button-next-${this.buttonId}`;
          slickArrowPrevButton.id = `button-prev-${this.buttonId}`;
        }

        setTimeout(function () {
          slickArrowNextButton.style.height = `${image.offsetHeight}px`;
          slickArrowPrevButton.style.height = `${image.offsetHeight}px`;
        }, 100);
      }
    }
  }

  /**
   * Remove class 'hidden' from all slides
   */
  removeHiddenClass() {
    for (let slide of this.slides) {
      slide.classList.remove(this.classes.hidden);
    }
  }

  /**
   * Get selector
   */
  static getSelector() {
    return `[${attributeBase}]`;
  }
}
