import React, { useState } from 'react';
import { useSwipeable } from './utils/index';
import {
  SmaellCarouselWrapper,
  CarouselContainer,
  CarouselSlot,
  SlideButtonLeft,
  SlideButtonRight
} from './styles';
import { Grid } from '@mui/material';
import { NEXT, PREV } from './types';
import type { SmallCarouselProps } from './types';
import { ASSETS_URL } from '../../consts/common';

export type Direction = typeof PREV | typeof NEXT;

interface CarouselState {
  pos: number;
  sliding: boolean;
  dir: Direction;
}

type CarouselAction = { type: Direction; numItems: number } | { type: 'stopSliding' };

const getOrder = (index: number, pos: number, numItems: number) => {
  return index - pos < 0 ? numItems - Math.abs(index - pos) : index - pos;
};

const getInitialState = (numItems: number): CarouselState => ({
  pos: numItems - 1,
  sliding: false,
  dir: NEXT
});

const SmallCarousel = ({
  isSmall,
  children,
  leftClickEvent,
  rightClickEvent,
  className,
  width
}: SmallCarouselProps) => {
  const [disSlide, setDisSlide] = useState(false);
  const numItems = React.Children.count(children);
  const [state, dispatch] = React.useReducer(reducer, getInitialState(numItems));

  const disableSlide = () => {
    setTimeout(() => {
      setDisSlide(false);
    }, 1000);
  };

  const slide = (dir: Direction) => {
    if (disSlide) return;
    dispatch({ type: dir, numItems });
    setTimeout(() => {
      dispatch({ type: 'stopSliding' });
    }, 50);
    setDisSlide(true);
    disableSlide();
  };

  const handlers = useSwipeable({
    onSwipedLeft: () => slide(NEXT),
    onSwipedRight: () => slide(PREV),
    swipeDuration: 500,
    preventScrollOnSwipe: false,
    trackMouse: false
  });

  function reducer(state: CarouselState, action: CarouselAction): CarouselState {
    switch (action.type) {
      case PREV:
        return {
          ...state,
          dir: PREV,
          sliding: true,
          pos: state.pos === 0 ? numItems - 1 : state.pos - 1
        };
      case NEXT:
        return {
          ...state,
          dir: NEXT,
          sliding: true,
          pos: state.pos === numItems - 1 ? 0 : state.pos + 1
        };
      case 'stopSliding':
        return { ...state, sliding: false };
      default:
        return state;
    }
  }

  return (
    <div {...handlers}>
      <Grid className={className} container alignItems="center" wrap="nowrap">
        <Grid item>
          <SlideButtonLeft
            customSize={64}
            src={`${ASSETS_URL}/icons2/icon_bigArrow.svg`}
            onClick={() => {
              leftClickEvent();
              slide(PREV);
            }}
          />
        </Grid>
        <SmaellCarouselWrapper isSmall={isSmall} item>
          <CarouselContainer
            width={width}
            isSmall={isSmall}
            dir={state.dir}
            sliding={state.sliding}
          >
            {React.Children.map(children, (child, index) => (
              <CarouselSlot isSmall={isSmall} order={getOrder(index, state.pos, numItems)}>
                {child}
              </CarouselSlot>
            ))}
          </CarouselContainer>
        </SmaellCarouselWrapper>
        <Grid item>
          <SlideButtonRight
            customSize={64}
            src={`${ASSETS_URL}/icons2/icon_bigArrow.svg`}
            onClick={() => {
              rightClickEvent();
              slide(NEXT);
            }}
          />
        </Grid>
      </Grid>
    </div>
  );
};

export default SmallCarousel;
