import { Duration } from "@gnu-taler/taler-util";
import { VNode, h } from "preact";
import { UIFormProps } from "../FormProvider.js";
import { InputLine } from "./InputLine.js";

const PATTERN = /^(?<value>[0-9]+)(?<unit>[smhDMY])$/;
const UNIT_GROUP = "unit";
const VALUE_GROUP = "value";

type DurationUnit = "s" | "m" | "h" | "D" | "M" | "Y";
type DurationSpec = Parameters<typeof Duration.fromSpec>[0];

type DurationValue = {
  unit: DurationUnit;
  value: number;
};

function updateSpec(spec: DurationSpec, value: DurationValue): void {
  switch (value.unit) {
    case "s": {
      spec.seconds = value.value;
      break;
    }
    case "m": {
      spec.minutes = value.value;
      break;
    }
    case "h": {
      spec.hours = value.value;
      break;
    }
    case "D": {
      spec.days = value.value;
      break;
    }
    case "M": {
      spec.months = value.value;
      break;
    }
    case "Y": {
      spec.years = value.value;
      break;
    }
  }
}

function parseDurationValue(str: string): DurationValue | undefined {
  const r = PATTERN.exec(str);
  if (!r) return undefined;
  const value = Number.parseInt(r.groups![VALUE_GROUP], 10);
  const unit = r.groups![UNIT_GROUP] as DurationUnit;
  return { value, unit };
}

export function InputDurationText(props: UIFormProps<string>): VNode {
  return (
    <InputLine
      type="text"
      {...props}
      converter={{
        //@ts-ignore
        fromStringUI: (v): Duration | undefined => {
          if (!v) return Duration.getForever();
          const spec = v.split(" ").reduce((prev, cur) => {
            const v = parseDurationValue(cur);
            if (v) {
              updateSpec(prev, v);
            }
            return prev;
          }, {} as DurationSpec);
          return Duration.fromSpecOrUndefined(spec);
        },
        //@ts-ignore
        toStringUI: (v?: Duration): string => {
          if (v === undefined) return "";
          // return v! as any;
          const spec = Duration.toSpec(v);
          let result = "";
          if (spec?.years) {
            result += `${spec.years}Y `;
          }
          if (spec?.month) {
            result += `${spec.month}M `;
          }
          if (spec?.days) {
            result += `${spec.days}D `;
          }
          if (spec?.hours) {
            result += `${spec.hours}h `;
          }
          if (spec?.minutes) {
            result += `${spec.minutes}m `;
          }
          if (spec?.seconds) {
            result += `${spec.seconds}s `;
          }
          return result.trimEnd();
        },
      }}
    />
  );
}
