/*
 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 
 */
import { ExchangeListItem } from "@gnu-taler/taler-util";
import { useState } from "preact/hooks";
import { useAlertContext } from "../context/alert.js";
import { ButtonHandler } from "../mui/handlers.js";
type State = State.Ready | State.NoExchangeFound | State.Selecting;
export namespace State {
  export interface NoExchangeFound {
    status: "no-exchange-found";
    error: undefined;
    currency: string;
    defaultExchange: string | undefined;
  }
  export interface Ready {
    status: "ready";
    doSelect: ButtonHandler;
    selected: ExchangeListItem;
  }
  export interface Selecting {
    status: "selecting-exchange";
    error: undefined;
    onSelection: (url: string) => Promise;
    onCancel: () => Promise;
    list: ExchangeListItem[];
    currency: string;
    initialValue: string;
  }
}
interface Props {
  currency: string;
  //there is a preference for the default at the initial state
  defaultExchange?: string;
  //list of exchanges
  list: ExchangeListItem[];
}
export function useSelectedExchange({
  currency,
  defaultExchange,
  list,
}: Props): State {
  const [isSelecting, setIsSelecting] = useState(false);
  const [selectedExchange, setSelectedExchange] = useState(
    undefined,
  );
  const { pushAlertOnError } = useAlertContext();
  if (!list.length) {
    return {
      status: "no-exchange-found",
      error: undefined,
      currency,
      defaultExchange,
    };
  }
  const exchangesWithThisCurrency = list.filter((e) => e.currency === currency);
  if (!exchangesWithThisCurrency.length) {
    // there should be at least one exchange for this currency
    return {
      status: "no-exchange-found",
      error: undefined,
      currency,
      defaultExchange,
    };
  }
  if (isSelecting) {
    const currentExchange =
      selectedExchange ??
      defaultExchange ??
      exchangesWithThisCurrency[0].exchangeBaseUrl;
    return {
      status: "selecting-exchange",
      error: undefined,
      list: exchangesWithThisCurrency,
      currency,
      initialValue: currentExchange,
      onSelection: async (exchangeBaseUrl: string) => {
        setIsSelecting(false);
        setSelectedExchange(exchangeBaseUrl);
      },
      onCancel: async () => {
        setIsSelecting(false);
      },
    };
  }
  {
    const found = !selectedExchange
      ? undefined
      : list.find((e) => e.exchangeBaseUrl === selectedExchange);
    if (found)
      return {
        status: "ready",
        doSelect: {
          onClick: pushAlertOnError(async () => setIsSelecting(true)),
        },
        selected: found,
      };
  }
  {
    const found = !defaultExchange
      ? undefined
      : list.find((e) => e.exchangeBaseUrl === defaultExchange);
    if (found)
      return {
        status: "ready",
        doSelect: {
          onClick: pushAlertOnError(async () => setIsSelecting(true)),
        },
        selected: found,
      };
  }
  return {
    status: "ready",
    doSelect: {
      onClick: pushAlertOnError(async () => setIsSelecting(true)),
    },
    selected: exchangesWithThisCurrency[0],
  };
}