/**
 * 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.addEventHandlers();
    this.initializeCarousel();
  }

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

      if (
        this.element.classList.contains(this.classes.slickInitialized) &&
        this.variant === this.attributes.photo &&
        !ElementHelpers.isDesktop()
      ) {
        this.positionDots();
      }
    });
  }

  /**
   * Declare attribute constants
   */
  get attributes() {
    return {
      image: `${attributeBase}-image`,
      wrapper: `${attributeBase}-wrapper`,
      dotsHeight: `${attributeBase}-dots-height`,
      slide: `${attributeBase}-slide`,
      textColor: `${attributeBase}-text-color`,
      dotsColor: `${attributeBase}-dots-color`,
      blogOverviewCarousel: 'blog-overview--carousel',
      blogOverviewGrid: 'blog-overview--grid',
      blogOverviewTopic: 'blog-overview--topic',
      photo: 'photo',
      quote: 'quote',
      cards: 'cards'
    };
  }

  /**
   * 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();
      if (this.variant === this.attributes.blogOverviewCarousel) {
        defaultSlickOptions.responsive[0].settings.slidesToShow = 2;
        $(this.element).slick(defaultSlickOptions);
      } else if (this.variant === this.attributes.blogOverviewGrid) {
        defaultSlickOptions.responsive[0].settings = 'unslick';
        $(this.element).slick(defaultSlickOptions);
      } else if (this.variant === this.attributes.blogOverviewTopic) {
        $(this.element).slick(defaultSlickOptions);
      } else if (this.variant === this.attributes.photo) {
        this.positionDots();

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

        const _this = this;

        /*
        * Find slide beforechange
        * NB: beforeChange should always come before slick initialisation
        * otherwise risk that slick is initialised before beforeChange is registered
        */
        $(this.element).on(
          'beforeChange',
          function (event, slick, currentSlide, nextSlide) {
            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');
            }
          }
        );

        /* settings for dots */
        $(this.element).slick(defaultSlickOptions);

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

        slickDots.style.bottom = '0px';

        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');
        }


      } else if (this.variant === this.attributes.quote) {
        defaultSlickOptions.dots = true;
        defaultSlickOptions.responsive = [
          {
            breakpoint: ElementHelpers.maxWidthMobileViewports(),
            settings: {
              swipe: false
            }
          }
        ];
        $(this.element).slick(defaultSlickOptions);
      } else if (this.variant === this.attributes.cards) {
        defaultSlickOptions.responsive[0].settings = 'unslick';
        $(this.element).slick(defaultSlickOptions);
      }
    }
    //if slider is carousel or topic, set arrow heights equal to images in slider on resize window
    if (
      this.variant === this.attributes.blogOverviewCarousel ||
      this.variant === this.attributes.blogOverviewTopic
    ) {
      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
      ) {
        setTimeout(function () {
          slickArrowNextButton.style.height = `${image.offsetHeight}px`;
          slickArrowPrevButton.style.height = `${image.offsetHeight}px`;
        }, 100);
      }
    }
  }

  /**
   * Position dots appended to photo or quote slider
   */
  positionDots() {
    this.dotsHeight = parseInt(
      ElementHelpers.getElementByAttributeWithinElement(
        this.element,
        this.attributes.dotsHeight
      ).offsetHeight
    );
    this.sliderDots = this.element.nextElementSibling;
    this.sliderDotsOffsetHeight = parseInt(this.sliderDots.offsetHeight);
    this.offsetTop = parseInt(this.element.offsetTop);
  }

  /**
   * 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}]`;
  }
}
