/*
 This file is part of GNU Taler
 (C) 2022 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/>
 */

import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { ContactEntry, opFixedSuccess, opKnownFailure } from "@gnu-taler/taler-util";
import { useCallback, useState } from "preact/hooks";
import { useBackendContext } from "../../context/backend.js";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
import { withSafe } from "../../mui/handlers.js";
import { RecursiveState } from "../../utils/index.js";
import { Props, State } from "./index.js";

export function useComponentState({ onBack, contact, noDebounce }: Props): RecursiveState<State> {
  const [alias, setAlias] = useState<string>();
  const [aliasType, setAliasType] = useState<string>();
  const [mailboxUri, setMailboxUri] = useState<string>();
  const [contactInState, setContactInState] = useState<ContactEntry>();
  const api = useBackendContext();
  const hook = useAsyncAsHook(() =>
    api.wallet.call(WalletApiOperation.GetContacts, {}),
  );
  const walletContacts = !hook ? [] : hook.hasError ? [] : hook.response.contacts
  
  if (!contactInState) {
    return (): State => {
      const found = (!contact) ? -1 : walletContacts.findIndex((e) => (e.alias == contact.alias) && (e.aliasType == contact.aliasType));
      const result = (found !== -1) ? 
        opKnownFailure("already-added"as const) :
        opFixedSuccess("ok"as const);
      const [inputError, setInputError] = useState<string>()

      return {
        status: "verify",
        error: undefined,
        onCancel: onBack,
        onAccept: async () => {
          if (!result || result.type !== "ok") return;
          setContactInState(contact)
        },
        alias: {
          value: alias ?? "",
          error: inputError,
          onInput: withSafe(async (x) => {setAlias(x)}, (e) => {
            setInputError(e.message)
          })
        },
        aliasType: {
          value: aliasType ?? "",
          error: inputError,
          onInput: withSafe(setAliasType, (e) => {
            setInputError(e.message)
          })
        },
        mailboxUri: {
          value: mailboxUri ?? "",
          error: inputError,
          onInput: withSafe(setMailboxUri, (e) => {
            setInputError(e.message)
          })
        },
        result,
      };

    }
  }

  async function addContactInternal(): Promise<void> {
    if (!contactInState) return;
    await api.wallet.call(WalletApiOperation.AddContact, { contact: contactInState });
    onBack();
  }
  return {
    status: "confirm",
    error: undefined,
    onCancel: onBack,
    onConfirm: addContactInternal,
    contact: contactInState ?? contact,
  }
}
