import { TranslatedString } from "@gnu-taler/taler-util";
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
import { FormProvider, UIFormProps } from "./FormProvider.js";
import { LabelWithTooltipMaybeRequired } from "./InputLine.js";
import { RenderAllFieldsByUiConfig, UIFormField } from "./forms.js";
import { useField } from "./useField.js";

function Option({
  label,
  disabled,
  isFirst,
  isLast,
  isSelected,
  onClick,
}: {
  label: TranslatedString;
  isFirst?: boolean;
  isLast?: boolean;
  isSelected?: boolean;
  disabled?: boolean;
  onClick: () => void;
}): VNode {
  let clazz = "relative flex border p-4 focus:outline-none disabled:text-grey";
  if (isFirst) {
    clazz += " rounded-tl-md rounded-tr-md ";
  }
  if (isLast) {
    clazz += " rounded-bl-md rounded-br-md ";
  }
  if (isSelected) {
    clazz += " z-10 border-indigo-200 bg-indigo-50 ";
  } else {
    clazz += " border-gray-200";
  }
  if (disabled) {
    clazz +=
      " cursor-not-allowed bg-gray-50 text-gray-500 ring-gray-200  text-gray";
  } else {
    clazz += " cursor-pointer";
  }
  return (
    <label class={clazz}>
      <input
        type="radio"
        name="privacy-setting"
        checked={isSelected}
        disabled={disabled}
        onClick={onClick}
        class="mt-0.5 h-4 w-4 shrink-0 text-indigo-600 disabled:cursor-not-allowed disabled:bg-gray-50 disabled:text-gray-500 disabled:ring-gray-200  focus:ring-indigo-600"
        aria-labelledby="privacy-setting-0-label"
        aria-describedby="privacy-setting-0-description"
      />
      <span class="ml-3 flex flex-col">
        <span
          id="privacy-setting-0-label"
          disabled
          class="block text-sm font-medium"
        >
          {label}
        </span>
        {/* <!-- Checked: "text-indigo-700", Not Checked: "text-gray-500" --> */}
        {/* <span
        id="privacy-setting-0-description"
        class="block text-sm"
      >
        This project would be available to anyone who has the link
      </span> */}
      </span>
    </label>
  );
}

export function noHandlerPropsAndNoContextForField(
  field: string | number | symbol,
): never {
  throw Error(
    `Field ${field.toString()} doesn't have handler and is not in a form provider context.`,
  );
}

export function InputArray<T extends object, K extends keyof T>(
  props: {
    fields: UIFormField[];
    labelField: string;
  } & UIFormProps<T, K>,
): VNode {
  const { fields, labelField, name, label, required, tooltip } = props;
  // const { value, onChange, state } = useField<T, K>(name);
  //FIXME: remove deprecated
  const fieldCtx = useField<T, K>(props.name);
  if (!props.handler && !fieldCtx) {
    throw Error("");
  }
  const { value, onChange, state } =
    props.handler ?? fieldCtx ?? noHandlerPropsAndNoContextForField(props.name);

  const list = (value ?? []) as Array<Record<string, string | undefined>>;
  const [selectedIndex, setSelected] = useState<number | undefined>(undefined);
  const selected =
    selectedIndex === undefined ? undefined : list[selectedIndex];
    
  return (
    <div class="sm:col-span-6">
      <LabelWithTooltipMaybeRequired
        label={label}
        required={required}
        tooltip={tooltip}
      />

      <div class="-space-y-px rounded-md bg-white ">
        {list.map((v, idx) => {
          const label = getValueDeeper(v, labelField.split("."))
          return (
            <Option
              label={label as TranslatedString}
              key={idx}
              isSelected={selectedIndex === idx}
              isLast={idx === list.length - 1}
              disabled={selectedIndex !== undefined && selectedIndex !== idx}
              isFirst={idx === 0}
              onClick={() => {
                setSelected(selectedIndex === idx ? undefined : idx);
              }}
            />
          );
        })}
        {!state.disabled && (
          <div class="pt-2">
            <Option
              label={"Add..." as TranslatedString}
              isSelected={selectedIndex === list.length}
              isLast
              isFirst
              disabled={
                selectedIndex !== undefined && selectedIndex !== list.length
              }
              onClick={() => {
                setSelected(
                  selectedIndex === list.length ? undefined : list.length,
                );
              }}
            />
          </div>
        )}
      </div>
      {selectedIndex !== undefined && (
        /**
         * This form provider act as a substate of the parent form
         * Consider creating an InnerFormProvider since not every feature is expected
         */
        <FormProvider
          initial={selected}
          readOnly={state.disabled}
          computeFormState={(v) => {
            // current state is ignored
            // the state is defined by the parent form

            // elements should be present in the state object since this is expected to be an array
            //@ts-ignore
            // return state.elements[selectedIndex];
            return {};
          }}
          onSubmit={(v) => {
            const newValue = [...list];
            newValue.splice(selectedIndex, 1, v);
            onChange(newValue as any);
            setSelected(undefined);
          }}
          onUpdate={(v) => {
            const newValue = [...list];
            newValue.splice(selectedIndex, 1, v);
            onChange(newValue as any);
          }}
        >
          <div class="px-4 py-6">
            <div class="grid grid-cols-1 gap-y-8 ">
              <RenderAllFieldsByUiConfig fields={fields} />
            </div>
          </div>
        </FormProvider>
      )}
      {selectedIndex !== undefined && (
        <div class="flex items-center pt-3">
          <div class="flex-auto">
            {selected !== undefined && (
              <button
                type="button"
                onClick={() => {
                  const newValue = [...list];
                  newValue.splice(selectedIndex, 1);
                  onChange(newValue as any);
                  setSelected(undefined);
                }}
                class="block rounded-md bg-red-600 px-3 py-2 text-center text-sm  text-white shadow-sm hover:bg-red-500 "
              >
                Remove
              </button>
            )}
          </div>
        </div>
      )}
    </div>
  );
}



export function getValueDeeper(
  object: Record<string, any>,
  names: string[],
): string {
  if (names.length === 0) {
    return object as any as string;
  }
  const [head, ...rest] = names;
  if (!head) {
    return getValueDeeper(object, rest);
  }
  if (object === undefined) {
    return ""
  }
  return getValueDeeper(object[head], rest);
}


