/*
 This file is part of GNU Taler
 (C) 2021-2024 Taler Systems S.A.

 GNU Taler is free software; you can redistribute it and/or modify it under the
 terms of the GNU General Public License as published by the Free Software
 Foundation; either version 3, or (at your option) any later version.

 GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

 You should have received a copy of the GNU General Public License along with
 GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */

/**
 *
 * @author Sebastian Javier Marchano (sebasjm)
 */
import { Duration } from "@gnu-taler/taler-util";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { formatDuration, intervalToDuration } from "date-fns";
import { ComponentChildren, h, VNode } from "preact";
import { useState } from "preact/hooks";
import { SimpleModal } from "../modal/index.js";
import { DurationPicker } from "../picker/DurationPicker.js";
import { InputProps, useField } from "./useField.js";


const TALER_SCREEN_ID = 8;

export interface Props<T> extends InputProps<T> {
  expand?: boolean;
  readonly?: boolean;
  withForever?: boolean;
  side?: ComponentChildren;
  withoutClear?: boolean;
  useProtocolDuration?: boolean;
}

export function InputDuration<T>({
  name,
  expand,
  placeholder,
  tooltip,
  label,
  help,
  readonly,
  withForever,
  withoutClear,
  side,
  useProtocolDuration,
}: Props<keyof T>): VNode {
  const [opened, setOpened] = useState(false);
  const { i18n } = useTranslationContext();

  const { error, required, value: anyValue, onChange } = useField<T>(name);
  let strValue = "";
  const value: Duration =
    anyValue && anyValue.d_us !== undefined
      ? Duration.fromTalerProtocolDuration(anyValue)
      : anyValue;
  if (!value) {
    strValue = "";
  } else if (value.d_ms === "forever") {
    strValue = i18n.str`Forever`;
  } else {
    if (value.d_ms === undefined) {
      throw Error(
        `assertion error: duration should have a d_ms but got '${JSON.stringify(
          value,
        )}'`,
      );
    }
    strValue = formatDuration(
      intervalToDuration({ start: 0, end: value.d_ms }),
      {
        locale: {
          formatDistance: (name, value) => {
            switch (name) {
              case "xMonths":
                return i18n.str`${value}M`;
              case "xYears":
                return i18n.str`${value}Y`;
              case "xDays":
                return i18n.str`${value}d`;
              case "xHours":
                return i18n.str`${value}h`;
              case "xMinutes":
                return i18n.str`${value}min`;
              case "xSeconds":
                return i18n.str`${value}sec`;
              default:
                throw Error("not reached");
            }
          },
          localize: {
            day: () => "s",
            month: () => "m",
            ordinalNumber: () => "th",
            dayPeriod: () => "p",
            quarter: () => "w",
            era: () => "e",
          },
        },
      },
    );
  }

  return (
    <div class="field is-horizontal">
      <div class="field-label is-normal">
        <label class="label">
          {label}
          {tooltip && (
            <span class="icon" data-tooltip={tooltip}>
              <i class="mdi mdi-information" />
            </span>
          )}
        </label>
      </div>

      <div class="field-body is-flex-grow-3">
        <div class="field">
          <div class="field has-addons">
            <p class={expand ? "control is-expanded " : "control "}>
              <input
                class="input"
                type="text"
                readonly
                value={strValue}
                placeholder={placeholder}
                onClick={() => {
                  if (!readonly) setOpened(true);
                }}
              />
              {required && (
                <span class="icon has-text-danger is-right">
                  <i class="mdi mdi-alert" />
                </span>
              )}
            </p>
            <div
              class="control"
              onClick={() => {
                if (!readonly) setOpened(true);
              }}
            >
              <a class="button is-static">
                <span class="icon">
                  <i class="mdi mdi-clock" />
                </span>
              </a>
            </div>
          </div>
          {error && (
            <p class="help is-danger" style={{ fontSize: 16 }}>
              {error}
            </p>
          )}
          <span class="has-text-grey">{help}</span>
        </div>

        {withForever && (
          <span data-tooltip={i18n.str`Change value to never`}>
            <button
              type="button"
              class="button is-info mr-3"
              onClick={() => onChange({ d_ms: "forever" } as any)}
            >
              <i18n.Translate>Forever</i18n.Translate>
            </button>
          </span>
        )}
        {!readonly && !withoutClear && (
          <span data-tooltip={i18n.str`Change value to empty`}>
            <button
              type="button"
              class="button is-info "
              onClick={() => onChange(undefined as any)}
            >
              <i18n.Translate>Clear</i18n.Translate>
            </button>
          </span>
        )}
        {side}
      </div>

      {opened && (
        <SimpleModal onCancel={() => setOpened(false)}>
          <DurationPicker
            days
            hours
            minutes
            value={!value || value.d_ms === "forever" ? 0 : value.d_ms}
            onChange={(v) => {
              let duration: any = { d_ms: v};
              if (useProtocolDuration === true) {
                onChange(Duration.toTalerProtocolDuration(duration) as any);
              } else {
                onChange(duration);
              }
            }}
          />
        </SimpleModal>
      )}
    </div>
  );
}
