import { useEffect } from "react";
import { DropHalf } from "@phosphor-icons/react";
import { commandIds } from "@commands/ids";
import type { ImageDocument } from "@core/document";
import type { AppStore } from "@editor/store";
import type { ChromaKeySettings } from "@editor/tools";
import type { SelectionState } from "@editor/state";
import { applyChromaKeyMask, previewChromaKey, resolveChromaKeyTarget } from "@operations/masks/chromaKey";
import { BottomControlColorPicker } from "./ColorPicker";
import { BottomControlDivider } from "./Divider";
import { BottomControlSlider } from "./Slider";
import { bottomControlFieldClass, bottomControlIconSlotClass, bottomControlLabelClass, bottomControlMenuClass } from "./styles";

export type ChromaKeyControlsProps = {
  document: ImageDocument;
  selection: SelectionState;
  settings: ChromaKeySettings;
  dispatch: AppStore["dispatch"];
};

export function ChromaKeyControls({ document, selection, settings, dispatch }: ChromaKeyControlsProps) {
  const target = resolveChromaKeyTarget(document, selection);

  useEffect(() => {
    return () => {
      dispatch(commandIds.toolSetBrushStrokePreview, undefined);
    };
  }, [dispatch]);

  useEffect(() => {
    let cancelled = false;

    if (!target) {
      dispatch(commandIds.toolSetBrushStrokePreview, undefined);
      return;
    }

    void previewChromaKey(target.asset.source, target.asset.intrinsicSize.w, target.asset.intrinsicSize.h, settings).then((source) => {
      if (cancelled) return;
      dispatch(commandIds.toolSetBrushStrokePreview, { layerId: target.layer.id, assetId: target.asset.id, source });
    });

    return () => {
      cancelled = true;
    };
  }, [dispatch, settings.choke, settings.color, settings.despeckle, settings.feather, settings.softness, settings.spill, settings.tolerance, target?.asset.id, target?.asset.source, target?.asset.intrinsicSize.w, target?.asset.intrinsicSize.h, target?.layer.id]);

  return (
    <div className={bottomControlMenuClass()}>
      <span className={bottomControlIconSlotClass()} title="Chroma key">
        <DropHalf size={24} weight="regular" />
      </span>
      <BottomControlDivider />
      <label className={bottomControlFieldClass()}>
        <span className={bottomControlLabelClass()}>Key</span>
        <BottomControlColorPicker
          value={settings.color}
          aria-label="Chroma key color"
          onValueChange={(color) => dispatch(commandIds.toolSetChromaKeySettings, { color })}
        />
      </label>
      <BottomControlDivider />
      <label className={bottomControlFieldClass()}>
        <span className={bottomControlLabelClass()}>Tol</span>
        <BottomControlSlider
          min={0}
          max={255}
          value={settings.tolerance}
          className="w-36"
          aria-label="Chroma key tolerance"
          onValueChange={(tolerance) => dispatch(commandIds.toolSetChromaKeySettings, { tolerance })}
        />
        <span className="w-10 text-right text-base text-white">{Math.round(settings.tolerance)}</span>
      </label>
      <BottomControlDivider />
      <label className={bottomControlFieldClass()}>
        <span className={bottomControlLabelClass()}>Soft</span>
        <BottomControlSlider
          min={0}
          max={255}
          value={settings.softness}
          className="w-36"
          aria-label="Chroma key edge softness"
          onValueChange={(softness) => dispatch(commandIds.toolSetChromaKeySettings, { softness })}
        />
        <span className="w-10 text-right text-base text-white">{Math.round(settings.softness)}</span>
      </label>
      <BottomControlDivider />
      <label className={bottomControlFieldClass()}>
        <span className={bottomControlLabelClass()}>Feather</span>
        <BottomControlSlider
          min={0}
          max={20}
          value={settings.feather}
          className="w-32"
          aria-label="Chroma key mask feather"
          onValueChange={(feather) => dispatch(commandIds.toolSetChromaKeySettings, { feather })}
        />
        <span className="w-8 text-right text-base text-white">{Math.round(settings.feather)}</span>
      </label>
      <BottomControlDivider />
      <label className={bottomControlFieldClass()}>
        <span className={bottomControlLabelClass()}>Choke</span>
        <BottomControlSlider
          min={-20}
          max={20}
          value={settings.choke}
          className="w-32"
          aria-label="Chroma key mask choke or expand"
          onValueChange={(choke) => dispatch(commandIds.toolSetChromaKeySettings, { choke })}
        />
        <span className="w-8 text-right text-base text-white">{Math.round(settings.choke)}</span>
      </label>
      <BottomControlDivider />
      <label className={bottomControlFieldClass()}>
        <span className={bottomControlLabelClass()}>Clean</span>
        <BottomControlSlider
          min={0}
          max={20}
          value={settings.despeckle}
          className="w-32"
          aria-label="Chroma key mask despeckle"
          onValueChange={(despeckle) => dispatch(commandIds.toolSetChromaKeySettings, { despeckle })}
        />
        <span className="w-8 text-right text-base text-white">{Math.round(settings.despeckle)}</span>
      </label>
      <BottomControlDivider />
      <label className={bottomControlFieldClass()}>
        <span className={bottomControlLabelClass()}>Spill</span>
        <BottomControlSlider
          min={0}
          max={100}
          value={settings.spill}
          className="w-36"
          aria-label="Chroma key spill suppression"
          onValueChange={(spill) => dispatch(commandIds.toolSetChromaKeySettings, { spill })}
        />
        <span className="w-10 text-right text-base text-white">{Math.round(settings.spill)}</span>
      </label>
      <BottomControlDivider />
      <button
        type="button"
        className="rounded-full bg-white px-5 py-2 text-base font-medium text-black transition hover:bg-white/90 disabled:pointer-events-none disabled:opacity-35"
        disabled={!target}
        title={target ? "Create or update a layer mask from the chroma key" : "Select one image or raster layer to create a chroma key mask"}
        onClick={() => target && void applyChromaKeyMask(target, settings, dispatch)}
      >
        {target?.maskAsset ? "Update Mask" : "Create Mask"}
      </button>
    </div>
  );
}
