import React, { useEffect, useState, useRef } from 'react';
import { fromEvent } from 'rxjs';
import { throttleTime } from 'rxjs/operators';

import { OuterWrapper, Wrapper, Rail, Track } from './styled';

type Props = {
  color?: 'primary' | 'secondary';
  minimum?: number;
  maximum?: number;
  defaultValue?: number;
  value?: number;
  disabled?: boolean;
  onChange?: (value: number) => void;
};

const Sliders: React.FC<Props> = ({
  defaultValue = 0,
  value = 0,
  onChange,
  // minimum = 0,
  maximum = 100,
}: Props) => {
  const sliderRef = useRef<HTMLDivElement>(null);
  const [valueState, setValueState] = useState(defaultValue);
  const [isActive, setActive] = useState(false);
  let mouseSubscription: any = null;
  let touchSubscription: any = null;

  const parseValueToPercent = (val: number): number => Math.floor(val * 100);

  const getFingerMoveValue = (event: any): void => {
    const { current: slider } = sliderRef;
    let clientX = 0;

    if (event.touches) {
      const touches = event.touches[0];
      ({ clientX } = touches);
    } else {
      ({ clientX } = event);
    }

    if (slider) {
      const { width, left } = slider.getBoundingClientRect();
      const moveDistance = clientX - left;
      const moveRate = moveDistance / width;
      let percent = parseValueToPercent(moveRate);

      if (percent <= 0) {
        percent = 0;
      } else if (percent >= 100) {
        percent = 100;
      }

      if (onChange) {
        const val = Math.floor(percent * (maximum * 0.01));
        onChange(val);
      }
    }
  };

  const handleTouchMove = (event: any): void => {
    event.preventDefault();
    getFingerMoveValue(event);
  };

  const handleTouchEnd = (event: MouseEvent): void => {
    event.preventDefault();

    setActive(false);
    mouseSubscription.unsubscribe();
    touchSubscription.unsubscribe();
  };

  const handleMouseDown = (
    event: React.MouseEvent<HTMLElement> | React.TouchEvent<HTMLElement>
  ): void => {
    event.preventDefault();

    getFingerMoveValue(event);
    setActive(true);

    mouseSubscription = fromEvent(document.body, 'mousemove')
      .pipe(throttleTime(35))
      .subscribe(handleTouchMove);
    touchSubscription = fromEvent(document.body, 'touchmove')
      .pipe(throttleTime(35))
      .subscribe(handleTouchMove);
    document.body.addEventListener('mouseup', handleTouchEnd);
  };

  const setPercent = (): void => {
    const percent = parseValueToPercent((defaultValue || value) / maximum);
    setValueState(percent);
  };

  useEffect(() => {
    setPercent();
  }, []);

  useEffect(() => {
    setPercent();
  }, [value]);

  return (
    <OuterWrapper>
      <Wrapper
        ref={sliderRef}
        data-testid="sliders"
        onMouseDown={handleMouseDown}
        onTouchStart={handleMouseDown}
      >
        <Rail track={valueState} />
        <Track data-testid="track" track={valueState} isActive={isActive} />
      </Wrapper>
    </OuterWrapper>
  );
};

export default Sliders;
