import { TouchEventFunction, View } from "@tarojs/components";
import React, { CSSProperties, useEffect, useState } from "react";
import styles from "./oui-picker-item.module.scss";

class OuiPickerItemEntity {
  label: string;
  value: string | number;
}

interface OuiPickerItemProps {
  className?: string;
  data: OuiPickerItemEntity[];
  value?: string | number;
  onChange?: Function;
  style?: CSSProperties;
}

/**
 * Picker组件，部分借鉴/使用了TDesign的代码，感谢腾讯TDesign团队
 */
function OuiPickerItem({
  className,
  data,
  value,
  onChange = (index, item) => {
    console.log(index, item);
  },
  style,
}: OuiPickerItemProps) {
  const height = 36;

  const [, setIndex] = useState<number>(0);

  const [offset, setOffset] = useState<number>(0);

  const [startOffset, setStartOffset] = useState<number>(0);
  const [startY, setStartY] = useState<number>(0);

  const [duration, setDuration] = useState<number>(0);

  const itemsStyle = (): CSSProperties => {
    return {
      transform: `translateY(${offset + height * 2}px)`,
      transition: `transform ${duration}ms cubic-bezier(0.215, 0.61, 0.355, 1)`,
    };
  };

  const itemStyle = (): CSSProperties => {
    return {
      height: `${height}px`,
    };
  };

  const count = (): number => {
    return data.length;
  };

  const calculateViewDeltaY = (
    touchDeltaY: number,
    itemHeight: number
  ): number => {
    return Math.abs(touchDeltaY) > itemHeight ? 1.2 * touchDeltaY : touchDeltaY;
  };

  const range = (num: number, min: number, max: number) => {
    return Math.min(Math.max(num, min), max);
  };

  const onTouchStart: TouchEventFunction = (e) => {
    setStartY(e.touches[0].clientY);
    setStartOffset(offset);
    setDuration(0);
  };

  const onTouchMove: TouchEventFunction = (e) => {
    const touchDeltaY = e.touches[0].clientY - startY;
    const deltaY = calculateViewDeltaY(touchDeltaY, height);
    setOffset(range(startOffset + deltaY, -(count() * height), 0));
    setDuration(240);
  };

  const onTouchEnd: TouchEventFunction = () => {
    if (offset === startOffset) {
      return;
    }
    const current = range(Math.round(-offset / height), 0, count() - 1);
    setIndex(current);
    setOffset(-current * height);
    onChange(current, data[current]);
  };

  useEffect(() => {
    for (let i = 0; i < data.length; i++) {
      const item = data[i];
      if (item.value === value) {
        setIndex(i);
        setOffset(-i * height);
      }
    }
  }, [value]);

  return (
    <View
      className={`${styles.component} ${className}`}
      style={{ ...style }}
      onTouchStart={onTouchStart}
      onTouchMove={onTouchMove}
      onTouchEnd={onTouchEnd}
    >
      <View className={styles.items} style={{ ...itemsStyle() }}>
        {data.map((item) => (
          <View className={styles.item} style={{ ...itemStyle() }}>
            {item.label}
          </View>
        ))}
      </View>
    </View>
  );
}

export default OuiPickerItem;

export { OuiPickerItemEntity };
