import { SliderSlots, SlotsToClasses, slider } from '@trail-ui/theme';
import { useMemo, useRef } from 'react';
import { useSliderState } from 'react-stately';
import {
  mergeProps,
  useFocusRing,
  useNumberFormatter,
  useSlider,
  useSliderThumb,
  VisuallyHidden,
} from 'react-aria';

export interface SliderProps {
  label?: string;
  isDisabled?: boolean;
  formatOptions?: Intl.NumberFormatOptions;
  name?: string;
  classNames?: SlotsToClasses<SliderSlots>;
  maxValue?: number;
  defaultValue?: number | number[];
  step?: number;
  onChange?: (value: number | number[]) => void;
}

function Slider({ label, formatOptions, name, classNames, ...props }: SliderProps) {
  const slots = useMemo(() => slider(), []);

  let trackRef = useRef(null);
  let numberFormatter = useNumberFormatter(formatOptions);
  let state = useSliderState({ ...props, numberFormatter });
  let { groupProps, trackProps, labelProps, outputProps } = useSlider(props, state, trackRef);

  return (
    <div {...groupProps}>
      <div>
        <label {...labelProps}>{label}</label>
      </div>
      <div
        className={`${slots.base({ class: classNames?.base })} ${state.isDisabled && slots.disableMouseEvents({ class: classNames?.disableMouseEvents })}`}
      >
        <div
          {...trackProps}
          ref={trackRef}
          className={slots.trackWrapper({ class: classNames?.trackWrapper })}
        >
          <div
            className={`${slots.track({ class: classNames?.track })} ${state.isDisabled && slots.disableTrack({ class: classNames?.disableTrack })}`}
          ></div>
          <div
            className={`${slots.fillTrack({ class: classNames?.fillTrack })} ${state.isDisabled && slots.disableFillTrack({ class: classNames?.disableFillTrack })}`}
            style={{ width: state.getThumbPercent(0) * 100 + '%' }}
          />
          <Thumb index={0} state={state} trackRef={trackRef} name={name} />
        </div>
        {label && (
          <div
            className={`${slots.value({ class: classNames?.value })} ${state.isDisabled && slots.disableValue({ class: classNames?.disableValue })}`}
          >
            <output {...outputProps}>{state.getThumbValueLabel(0)}%</output>
          </div>
        )}
      </div>
    </div>
  );
}

function Thumb(props: { state: any; trackRef: any; index: any; name: any }) {
  const slots = useMemo(() => slider(), []);

  let inputRef = useRef(null);
  let { state, trackRef, index, name } = props;
  let { thumbProps, inputProps } = useSliderThumb(
    {
      index,
      trackRef,
      inputRef,
      name,
    },
    state,
  );

  let { focusProps, isFocusVisible } = useFocusRing();
  return (
    <div
      {...thumbProps}
      className={`${slots.sliderThumb()} ${state.isDisabled && slots.disableFillTrack()} ${isFocusVisible && slots.focusRing()}`}
    >
      <VisuallyHidden>
        <input ref={inputRef} {...mergeProps(inputProps, focusProps)} />
      </VisuallyHidden>
    </div>
  );
}

function MultiSlider({ label, formatOptions, name, classNames, ...props }: SliderProps) {
  let trackRef = useRef(null);
  const slots = useMemo(() => slider(), []);

  let numberFormatter = useNumberFormatter(formatOptions);
  let state = useSliderState({ ...props, numberFormatter });
  let { groupProps, trackProps, labelProps, outputProps } = useSlider(props, state, trackRef);

  return (
    <div {...groupProps}>
      <div>
        <label {...labelProps}>{label}</label>
      </div>

      <div
        className={`${slots.base({ class: classNames?.base })} ${state.isDisabled && slots.disableMouseEvents({ class: classNames?.disableMouseEvents })}`}
      >
        {label && (
          <div
            className={`${slots.value({ class: classNames?.value })} ${state.isDisabled && slots.disableValue({ class: classNames?.disableValue })}`}
          >
            <output {...outputProps}>{state.getThumbValueLabel(0)}</output>
          </div>
        )}
        <div
          {...trackProps}
          ref={trackRef}
          className={slots.trackWrapper({ class: classNames?.trackWrapper })}
        >
          <div
            className={`${slots.track({ class: classNames?.track })} ${state.isDisabled && slots.disableTrack({ class: classNames?.disableTrack })}`}
          ></div>
          <div
            className={`${slots.fillTrack({ class: classNames?.fillTrack })} ${state.isDisabled && slots.disableFillTrack({ class: classNames?.disableFillTrack })}`}
            style={{
              left: `${state.getThumbPercent(0) * 100}%`,
              width: `${(state.getThumbPercent(1) - state.getThumbPercent(0)) * 100}%`,
            }}
          />
          <Thumb index={0} state={state} trackRef={trackRef} name={name} />
          <Thumb index={1} state={state} trackRef={trackRef} name={name} />
        </div>

        {label && (
          <div
            className={`${slots.value({ class: classNames?.value })} ${state.isDisabled && slots.disableValue({ class: classNames?.disableValue })}`}
          >
            <output {...outputProps}>{state.getThumbValueLabel(1)}</output>
          </div>
        )}
      </div>
    </div>
  );
}

export { Slider, MultiSlider };
