/*
 This file is part of GNU Taler
 (C) 2021-2023 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 {
  ErrorType,
  TranslationProvider,
  useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { Fragment, h, VNode } from "preact";
import { route } from "preact-router";
import { useMemo, useState } from "preact/hooks";
import { ApplicationReadyRoutes } from "./ApplicationReadyRoutes.js";
import { Loading } from "./components/exception/loading.js";
import {
  NotificationCard,
  NotYetReadyAppMenu,
} from "./components/menu/index.js";
import {
  BackendContextProvider,
  useBackendContext,
} from "./context/backend.js";
import { ConfigContextProvider } from "./context/config.js";
import { useBackendConfig } from "./hooks/backend.js";
import { strings } from "./i18n/strings.js";
import LoginPage from "./paths/login/index.js";
import { HttpStatusCode } from "@gnu-taler/taler-util";
import { Settings } from "./paths/settings/index.js";

export function Application(): VNode {
  return (
    // <FetchContextProvider>
    <BackendContextProvider>
      <TranslationProvider source={strings}>
        <ApplicationStatusRoutes />
      </TranslationProvider>
    </BackendContextProvider>
    // </FetchContextProvider>
  );
}

function ApplicationStatusRoutes(): VNode {
  const { updateLoginStatus, triedToLog } = useBackendContext();
  const result = useBackendConfig();
  const { i18n } = useTranslationContext();

  const updateLoginInfoAndGoToRoot = (url: string, token?: string) => {
    updateLoginStatus(url, token);
    route("/");
  };

  const { currency, version } = result.ok
    ? result.data
    : { currency: "unknown", version: "unknown" };
  const ctx = useMemo(() => ({ currency, version }), [currency, version]);

  const [showSettings, setShowSettings] = useState(false)

  if (showSettings) {
    return <Fragment>
      <NotYetReadyAppMenu onShowSettings={() => setShowSettings(true)} title="UI Settings" />
      <Settings />
    </Fragment>
  }

  if (!triedToLog) {
    return (
      <Fragment>
        <NotYetReadyAppMenu title="Welcome!" onShowSettings={() => setShowSettings(true)} />
        <LoginPage onConfirm={updateLoginInfoAndGoToRoot} />
      </Fragment>
    );
  }

  if (!result.ok) {
    if (result.loading) return <Loading />;
    if (
      result.type === ErrorType.CLIENT &&
      result.status === HttpStatusCode.Unauthorized
    ) {
      return (
        <Fragment>
          <NotYetReadyAppMenu title="Login" onShowSettings={() => setShowSettings(true)} />
          <LoginPage onConfirm={updateLoginInfoAndGoToRoot} />
        </Fragment>
      );
    }
    if (
      result.type === ErrorType.CLIENT &&
      result.status === HttpStatusCode.NotFound
    ) {
      return (
        <Fragment>
          <NotYetReadyAppMenu title="Error" onShowSettings={() => setShowSettings(true)} />
          <NotificationCard
            notification={{
              message: i18n.str`Server not found`,
              type: "ERROR",
              description: `Check your url`,
            }}
          />
          <LoginPage onConfirm={updateLoginInfoAndGoToRoot} />
        </Fragment>
      );
    }
    if (result.type === ErrorType.SERVER) {
      <Fragment>
        <NotYetReadyAppMenu title="Error" onShowSettings={() => setShowSettings(true)} />
        <NotificationCard
          notification={{
            message: i18n.str`Server response with an error code`,
            type: "ERROR",
            description: i18n.str`Got message ${result.message} from ${result.info?.url}`,
          }}
        />
        <LoginPage onConfirm={updateLoginInfoAndGoToRoot} />
      </Fragment>;
    }
    if (result.type === ErrorType.UNREADABLE) {
      <Fragment>
        <NotYetReadyAppMenu title="Error" onShowSettings={() => setShowSettings(true)} />
        <NotificationCard
          notification={{
            message: i18n.str`Response from server is unreadable, http status: ${result.status}`,
            type: "ERROR",
            description: i18n.str`Got message ${result.message} from ${result.info?.url}`,
          }}
        />
        <LoginPage onConfirm={updateLoginInfoAndGoToRoot} />
      </Fragment>;
    }
    return (
      <Fragment>
        <NotYetReadyAppMenu title="Error" onShowSettings={() => setShowSettings(true)} />
        <NotificationCard
          notification={{
            message: i18n.str`Unexpected Error`,
            type: "ERROR",
            description: i18n.str`Got message ${result.message} from ${result.info?.url}`,
          }}
        />
        <LoginPage onConfirm={updateLoginInfoAndGoToRoot} />
      </Fragment>
    );
  }

  return (
    <div class="has-navbar-fixed-top">
      <ConfigContextProvider value={ctx}>
        <ApplicationReadyRoutes />
      </ConfigContextProvider>
    </div>
  );
}
