/*
 This file is part of GNU Taler
 (C) 2022-2024 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 {
  urlPattern,
  useCurrentLocation,
  useNavigationContext,
  useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";

import { assertUnreachable } from "@gnu-taler/taler-util";
import { useEffect } from "preact/hooks";
import { ExchangeAmlFrame } from "./ExchangeAmlFrame.js";
import { useOfficer } from "./hooks/officer.js";
import { Cases } from "./pages/Cases.js";
import { Officer } from "./pages/Officer.js";
import { CaseDetails } from "./pages/CaseDetails.js";
import { CaseUpdate, SelectForm } from "./pages/CaseUpdate.js";
import { HandleAccountNotReady } from "./pages/HandleAccountNotReady.js";

export function Routing(): VNode {
  const session = useOfficer();

  if (session.state === "ready") {
    return (
      <ExchangeAmlFrame officer={session}>
        <PrivateRouting />
      </ExchangeAmlFrame>
    );
  }
  return (
    <ExchangeAmlFrame>
      <PublicRounting />
    </ExchangeAmlFrame>
  );
}

const publicPages = {
  config: urlPattern(/\/config/, () => "#/config"),
  login: urlPattern(/\/login/, () => "#/login"),
};

function PublicRounting(): VNode {
  const { i18n } = useTranslationContext();
  const location = useCurrentLocation(publicPages);
  // const { navigateTo } = useNavigationContext();
  // const { config, lib } = useExchangeApiContext();
  // const [notification, notify, handleError] = useLocalNotification();
  const session = useOfficer();

  switch (location.name) {
    case undefined: {
      if (session.state !== "ready") {
        return <HandleAccountNotReady officer={session} />;
      } else {
        return <div />;
      }
    }
    case "config": {
      return (
        <Fragment>
          <div class="sm:mx-auto sm:w-full sm:max-w-sm">
            <h2 class="text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">{i18n.str`Welcome to exchange config!`}</h2>
          </div>
        </Fragment>
      );
    }
    case "login": {
      return (
        <Fragment>
          <div class="sm:mx-auto sm:w-full sm:max-w-sm">
            <h2 class="text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">{i18n.str`Welcome to exchange config!`}</h2>
          </div>
        </Fragment>
      );
    }
    default:
      assertUnreachable(location);
  }
}

export const privatePages = {
  account: urlPattern(/\/account/, () => "#/account"),
  cases: urlPattern(/\/cases/, () => "#/cases"),
  caseUpdate: urlPattern<{ cid: string; type: string }>(
    /\/case\/(?<cid>[a-zA-Z0-9]+)\/new\/(?<type>[a-zA-Z0-9_.]+)/,
    ({ cid, type }) => `#/case/${cid}/new/${type}`,
  ),
  caseNew: urlPattern<{ cid: string }>(
    /\/case\/(?<cid>[a-zA-Z0-9]+)\/new/,
    ({ cid }) => `#/case/${cid}/new`,
  ),
  caseDetails: urlPattern<{ cid: string }>(
    /\/case\/(?<cid>[a-zA-Z0-9]+)/,
    ({ cid }) => `#/case/${cid}`,
  ),
};

function PrivateRouting(): VNode {
  const { navigateTo } = useNavigationContext();
  const location = useCurrentLocation(privatePages);
  useEffect(() => {
    if (location === undefined) {
      navigateTo(privatePages.account.url({}));
    }
  }, [location]);

  switch (location.name) {
    case undefined: {
      return <Fragment />;
    }
    case "account": {
      return <Officer />;
    }
    case "caseDetails": {
      return <CaseDetails account={location.values.cid} />;
    }
    case "caseUpdate": {
      return (
        <CaseUpdate account={location.values.cid} type={location.values.type} />
      );
    }
    case "caseNew": {
      return <SelectForm account={location.values.cid} />;
    }
    case "cases": {
      return <Cases />;
    }
    default:
      assertUnreachable(location);
  }
}
