/*
 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 {
  ExchangeListItem,
  ScopeInfo
} 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<void>;
    onCancel: () => Promise<void>;
    list: ExchangeListItem[];
    // scope: ScopeInfo;
    initialValue: string;
  }
}

interface Props {
  scope: ScopeInfo;
  //there is a preference for the default at the initial state
  defaultExchange?: string;
  //list of exchanges
  list: ExchangeListItem[];
}

export function useSelectedExchange({
  scope,
  defaultExchange,
  list,
}: Props): State {
  const [isSelecting, setIsSelecting] = useState(false);
  const [selectedExchange, setSelectedExchange] = useState<string | undefined>(
    undefined,
  );
  const { pushAlertOnError } = useAlertContext();

  if (!list.length) {
    return {
      status: "no-exchange-found",
      error: undefined,
      // scope,
      currency: scope.currency,
      defaultExchange,
    };
  }

  if (isSelecting) {
    const currentExchange =
      selectedExchange ??
      defaultExchange ??
      list[0].exchangeBaseUrl;
    return {
      status: "selecting-exchange",
      error: undefined,
      list: list,
      // scope,
      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: list[0],
  };
}
