"use client";

import cx from "classnames";
import React from "react";

import { useHydrationSafeId, useStatic } from "../../../utils/hooks";
import RangeSliderStatic from "./RangeSlider.static";

const CLASS_ROOT = "range-slider";

export type RangeSliderWidth = "default" | "fullwidth";

export interface RangeSliderConfig {
  connect?: boolean | boolean[];
  format?: (value: number) => string;
  handleAttributes?: Array<Record<string, any>>;
  pips?: {
    mode?: "positions" | "count" | "values";
    filter?: (value: number) => boolean;
    format?: (value: number) => string;
    values?: number[] | number;
    density?: number;
  };
  range: {
    min: number | number[];
    max: number | number[];
  };
  start: number[];
  [key: string]: any;
}

export interface RangeSliderProps extends React.HTMLAttributes<HTMLDivElement> {
  /** [noUiSlider config object](https://refreshless.com/nouislider/slider-options/) */
  config: RangeSliderConfig;
  /** insert arbitrary element after rangeslider */
  elementAfter?: React.ReactNode;
  /** insert arbitrary element before rangeslider */
  elementBefore?: React.ReactNode;
  /** render data-rangeslider attribute and initialize RangeSlider.static.js */
  hasDataAttr?: boolean;
  /** element id. required by RangeSlider.static.js and generated automatically in React environment. */
  id?: string;
  /** Invalid state */
  isInvalid?: boolean;
  /** width of the element */
  width?: RangeSliderWidth;
  /** Additional CSS classes */
  className?: string;
}

const defaultProps = {
  hasDataAttr: true,
  width: "default" as RangeSliderWidth,
};

const RangeSlider: React.FC<RangeSliderProps> = ({
  className,
  id,
  hasDataAttr = defaultProps.hasDataAttr,
  config,
  elementBefore,
  elementAfter,
  isInvalid,
  width = defaultProps.width,
  ...other
}) => {
  const [rangesliderRef] = useStatic(RangeSliderStatic as any);

  const currentId = useHydrationSafeId(id);

  const classes = cx(
    CLASS_ROOT,
    {
      [`${CLASS_ROOT}--${width}`]: width !== defaultProps.width,
    },
    className,
  );

  return (
    <>
      {elementBefore}
      <div
        id={currentId}
        className={classes}
        ref={rangesliderRef}
        data-rangeslider={hasDataAttr}
        data-rangeslider-config={JSON.stringify(config)}
        {...other}
      />
      {config.start.map((_, i) => {
        const inputId = `${currentId}-${i}`;
        return (
          <input key={inputId} type="hidden" id={inputId} name={inputId} />
        );
      })}
      {elementAfter}
    </>
  );
};

RangeSlider.displayName = "RangeSlider";

export { RangeSlider };
