/*
 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 { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { useState } from "preact/hooks";
import { alertFromError, useAlertContext } from "../../context/alert.js";
import { useBackendContext } from "../../context/backend.js";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
import { Props, State } from "./index.js";
import { buildTermsOfServiceState } from "./utils.js";
export function useComponentState({ exchangeUrl, onChange }: Props): State {
  const api = useBackendContext();
  const readOnly = !onChange;
  const [showContent, setShowContent] = useState(readOnly);
  const { i18n } = useTranslationContext();
  const { pushAlertOnError } = useAlertContext();
  /**
   * For the exchange selected, bring the status of the terms of service
   */
  const terms = useAsyncAsHook(async () => {
    const exchangeTos = await api.wallet.call(
      WalletApiOperation.GetExchangeTos,
      {
        exchangeBaseUrl: exchangeUrl,
        acceptedFormat: ["text/xml"],
      },
    );
    const state = buildTermsOfServiceState(exchangeTos);
    return { state };
  }, []);
  if (!terms) {
    return {
      status: "loading",
      error: undefined,
    };
  }
  if (terms.hasError) {
    return {
      status: "error",
      error: alertFromError(
        i18n.str`Could not load the status of the term of service`,
        terms,
      ),
    };
  }
  const { state } = terms.response;
  async function onUpdate(accepted: boolean): Promise {
    if (!state) return;
    if (accepted) {
      await api.wallet.call(WalletApiOperation.SetExchangeTosAccepted, {
        exchangeBaseUrl: exchangeUrl,
        etag: state.version,
      });
    } else {
      // mark as not accepted
      await api.wallet.call(WalletApiOperation.SetExchangeTosAccepted, {
        exchangeBaseUrl: exchangeUrl,
        etag: undefined,
      });
    }
    // setAccepted(accepted);
    if (!readOnly) onChange(accepted); //external update
  }
  const accepted = state.status === "accepted";
  const base = {
    error: undefined,
    showingTermsOfService: {
      value: showContent,
      button: {
        onClick: pushAlertOnError(async () => {
          setShowContent(!showContent);
        }),
      },
    },
    terms: state,
    termsAccepted: {
      value: accepted,
      button: {
        onClick: pushAlertOnError(async () => {
          const newValue = !accepted; //toggle
          await onUpdate(newValue);
          setShowContent(false);
        }),
      },
    },
  };
  if (showContent) {
    return {
      status: "show-content",
      error: undefined,
      terms: state,
      showingTermsOfService: readOnly ? undefined : base.showingTermsOfService,
      termsAccepted: readOnly ? undefined : base.termsAccepted,
    };
  }
  //showing buttons
  if (accepted) {
    return {
      status: "show-buttons-accepted",
      ...base,
    };
  } else {
    return {
      status: "show-buttons-not-accepted",
      ...base,
    };
  }
}