import { Dispatch, SetStateAction, useCallback, useEffect } from "react";
import { RGBType } from "./colorPickerSection";
import { FormProvider, useForm } from "react-hook-form";
import { hexToRgb, isValidRGBValue, rgbToHex } from "../../util/colorUtil";
import Input from "../input/input";
import NumberInput from "../input/numberInput";

export default function ColorInput({
  hex,
  rgb,
  setHex,
  setRGB,
}: {
  hex: string;
  rgb?: RGBType;
  setHex: Dispatch<SetStateAction<string>>;
  setRGB: Dispatch<SetStateAction<RGBType | undefined>>;
}) {
  type ColorPickerFormModel = {
    hex: string;
    r: string;
    g: string;
    b: string;
  };
  const getCurrentValues = useCallback(() => {
    return {
      hex: hex,
      r: rgb?.r.toString() ?? "",
      g: rgb?.g.toString() ?? "",
      b: rgb?.b.toString() ?? "",
    };
  }, [hex, rgb]);

  const methods = useForm<ColorPickerFormModel>({
    defaultValues: getCurrentValues(),
  });
  const {
    watch,
    formState: { isDirty },
    handleSubmit,
  } = methods;

  const updatedHex = watch("hex");
  const updatedRValue = watch("r");
  const updatedGValue = watch("g");
  const updatedBValue = watch("b");

  // resets Value after Submit
  useEffect(() => {
    methods.reset(getCurrentValues());
  }, [hex, rgb]);

  // submit RGB value change
  const submitRGBChange = (formData: ColorPickerFormModel) => {
    const rValue = Number(formData.r);
    const gValue = Number(formData.g);
    const bValue = Number(formData.b);

    const newRGB = { r: rValue, g: gValue, b: bValue };
    setRGB(newRGB);

    const newHex = rgbToHex(newRGB);
    setHex(newHex);
  };

  // submit hex value change
  const submitHexChange = (formData: ColorPickerFormModel) => {
    const newHex = formData.hex;
    setHex(newHex);

    const newRGB = hexToRgb(newHex);
    setRGB(newRGB);
  };

  // hex value gets updated
  useEffect(() => {
    if (hex === updatedHex || !isDirty) return;

    const isValidHex =
      /^#[0-9A-F]{6}[0-9a-f]{0,2}$/i.test(updatedHex) &&
      updatedHex.length === 7;
    if (!isValidHex) return;

    handleSubmit(submitHexChange)();
  }, [updatedHex]);

  // RGB value gets updated
  useEffect(() => {
    if (!isDirty) return;

    const rValue = Number(updatedRValue);
    const gValue = Number(updatedGValue);
    const bValue = Number(updatedBValue);

    const isValidRGB =
      isValidRGBValue(rValue) &&
      isValidRGBValue(gValue) &&
      isValidRGBValue(bValue);
    if (!isValidRGB) return;

    handleSubmit(submitRGBChange)();
  }, [updatedRValue, updatedBValue, updatedGValue]);

  return (
    <div className="w-full">
      <FormProvider {...methods}>
        <div className="grid grid-cols-5 w-full">
          <div className="sm:col-span-2 col-span-5">
            <Input
              label="Hex"
              name="hex"
              type="text"
              noBorder={true}
              wrapperClassName="border-brand-primary rounded-l-lg rounded-r-lg sm:border-b-2 sm:border-l-2 sm:border-t-2 border-2 sm:border-r-0 sm:rounded-r-none"
            />
          </div>
          <NumberInput
            label="R"
            noBorder={true}
            manipulateValues={false}
            name="r"
            wrapperClassName="border-brand-primary border-l-2 border-b-2 border-t-2 hidden sm:block col-span-1"
          />
          <NumberInput
            label="G"
            name="g"
            noBorder={true}
            manipulateValues={false}
            wrapperClassName="border-brand-primary border-l-2 border-b-2 border-t-2 hidden sm:block col-span-1"
          />
          <NumberInput
            label="B"
            name="b"
            noBorder={true}
            manipulateValues={false}
            wrapperClassName="border-brand-primary rounded-r-lg border-l-2 border-r-2 border-b-2 border-t-2 hidden sm:block col-span-1"
          />
        </div>
      </FormProvider>
    </div>
  );
}
