import { Fragment, VNode, h } from "preact";
import { useEffect, useState } from "preact/hooks";
import { UIFormProps } from "../FormProvider.js";
import { noHandlerPropsAndNoContextForField } from "./InputArray.js";
import { LabelWithTooltipMaybeRequired } from "./InputLine.js";

/**
 * Two-state (on/off) or tri-state (on/off/unselected) toggle.
 *
 * FIXME: Types would be clearer if two/tri state were different types.
 */
export function InputToggle(
  props: {
    threeState: boolean;
    defaultValue?: boolean;
    trueValue?: any;
    falseValue?: any;
    onlyTrueValue?: boolean;
  } & UIFormProps<boolean>,
): VNode {
  const {
    label,
    tooltip,
    help,
    required,
    threeState,
    disabled,
    trueValue = true,
    falseValue = false,
    onlyTrueValue = false,
  } = props;
  const { value, onChange, error } =
    props.handler ?? noHandlerPropsAndNoContextForField(props.name);
  const [dirty, setDirty] = useState<boolean>();

  const isOn = trueValue === value;

  if (props.hidden) {
    return <Fragment />;
  }

  return (
    <div class="sm:col-span-6">
      <div class="flex items-center justify-between">
        <LabelWithTooltipMaybeRequired
          label={label}
          required={required}
          tooltip={tooltip}
          name={props.name as string}
        />
        <button
          type="button"
          data-state={isOn ? "on" : value === undefined ? "undefined" : "off"}
          class="bg-indigo-600 data-[state=off]:bg-gray-200 data-[state=undefined]:bg-gray-200  relative inline-flex h-6 w-12 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2"
          role="switch"
          disabled={disabled}
          aria-labelledby="availability-label"
          aria-describedby="availability-description"
          onClick={() => {
            setDirty(true);
            if (value === falseValue && threeState) {
              return onChange(undefined as any);
            }
            if (onlyTrueValue && value === trueValue) {
              return onChange(undefined as any);
            }
            if (value === trueValue) {
              return onChange(falseValue);
            }
            return onChange(trueValue);
          }}
        >
          <span
            data-state={
              isOn
                ? "on"
                : value === undefined && threeState
                  ? "undefined"
                  : "off"
            }
            class="translate-x-6 data-[state=off]:translate-x-0 data-[state=undefined]:translate-x-3 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"
          ></span>
        </button>
      </div>
      {help && (
        <p class="mt-2 text-sm text-gray-500" id="email-description">
          {help}
        </p>
      )}
      {dirty !== undefined && error && (
        <p class="mt-2 text-sm text-red-600" id="email-error">
          {error}
        </p>
      )}
    </div>
  );
}
