/*

This file is part of GNU Taler
(C) 2021-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/>

*/

/**
 *
 * @author Sebastian Javier Marchano (sebasjm)
 * @author Nic Eigel
 */

import {ComponentChildren, Fragment, h, VNode} from "preact";
import {useEffect, useState} from "preact/hooks";
import {Paths} from "../../InstanceRoutes.js";
import {Notification} from "../../utils/types.js";
import {NavigationBar} from "./NavigationBar.js";
import {Sidebar} from "./SideBar.js";

function getInstanceTitle(path: string): string {
    switch (path) {
        case Paths.key_figures:
            return 'Key figures';
        case Paths.critical_errors:
            return 'Critical errors';
        case Paths.operating_status:
            return 'Operating status';
        case Paths.detail_view:
            return 'Inconsistencies';
        case Paths.amount_arithmethic_inconsistency_list:
            return `Amount arithmetic inconsistencies`;
        case Paths.bad_sig_losses_list:
            return `Bad sig losses`;
        case Paths.balance_list:
            return `Balances`;
        case Paths.closure_lag_list:
            return `Closure Lags`;
        case Paths.coin_inconsistency_list:
            return `Coin inconsistencies`;
        case Paths.denomination_key_validity_withdraw_inconsistency_list:
            return `Denomination key validity withdraw inconsistency`;
        case Paths.denomination_pending_list:
            return `Denominations pending`;
        case Paths.denomination_without_sig_list:
            return `Denominations without sigs`;
        case Paths.deposit_confirmation_list:
            return `Deposit confirmations`;
        case Paths.deposit_confirmation_update:
            return `Update deposit confirmation`;
        case Paths.emergency_list:
            return `Emergencies`;
        case Paths.emergency_by_count_list:
            return `Emergencies by count`;
        case Paths.exchange_signkey_list:
            return `Exchange signkeys`;
        case Paths.fee_time_inconsistency_list:
            return `Fee time inconsistencies`;
        case Paths.historic_denomination_revenue_list:
            return `Historic denomination revenue`;
        case Paths.misattribution_in_inconsistency_list:
            return `Misattribution in inconsistencies`;
        case Paths.progress_list:
            return `Progress`;
        case Paths.purse_not_closed_inconsistency_list:
            return `Purse not closed inconsistencies`;
        case Paths.purse_list:
            return `Purses`;
        case Paths.refresh_hanging_list:
            return `Refreshes hanging`;
        case Paths.reserve_balance_insufficient_inconsistency_list:
            return `Reserve balance insufficient inconsistencies`;
        case Paths.reserve_balance_summary_wrong_inconsistency_list:
            return `Reserve balance summary wrong inconsistencies`;
        case Paths.reserve_in_inconsistency_list:
            return `Reserves in inconsistencies`;
        case Paths.reserve_not_closed_inconsistency_list:
            return `Reserves not closed inconsistencies`;
        case Paths.row_inconsistency_list:
            return `Row inconsistencies`;
        case Paths.row_minor_inconsistency_list:
            return `Row minor inconsistencies`;
        case Paths.wire_format_inconsistency_list:
            return `Wire format inconsistencies`;
        case Paths.wire_out_inconsistency_list:
            return `Wire out inconsistencies`;
        case Paths.settings:
            return `Settings`;
        default:
            return "";
    }
}

interface MenuProps {
    title?: string;
    path: string;
    onShowSettings: () => void;
}

function WithTitle({
                       title,
                       children,
                   }: {
    title: string;
    children: ComponentChildren;
}): VNode {
    useEffect(() => {
        document.title = `Taler Backoffice: ${title}`;
    }, [title]);
    return <Fragment>{children}</Fragment>;
}

export function Menu({
                         onShowSettings,
                         title,
                         path,
                     }: MenuProps): VNode {
    const [mobileOpen, setMobileOpen] = useState(false);
    const titleWithSubtitle = getInstanceTitle(path.replace("app/#", ""));
    return (
        <WithTitle title={titleWithSubtitle}>
            <div
                class={mobileOpen ? "has-aside-mobile-expanded" : ""}
                onClick={() => setMobileOpen(false)}
            >
                <NavigationBar
                    onMobileMenu={() => setMobileOpen(!mobileOpen)}
                    title={titleWithSubtitle}
                />

                <Sidebar
                    onShowSettings={onShowSettings}
                    mobile={mobileOpen}
                />
            </div>
        </WithTitle>
    );
}

interface NotYetReadyAppMenuProps {
    title: string;
    onShowSettings: () => void;
}

interface NotifProps {
    notification?: Notification;
}

export function NotificationCard({notification: n}: NotifProps): VNode | null {
    if (!n) return null;
    return (
        <div class="notification">
            <div class="columns is-vcentered">
                <div class="column is-12">
                    <article
                        class={
                            n.type === "ERROR"
                                ? "message is-danger"
                                : n.type === "WARN"
                                    ? "message is-warning"
                                    : "message is-info"
                        }
                    >
                        <div class="message-header">
                            <p>{n.message}</p>
                        </div>
                        {n.description && (
                            <div class="message-body">
                                <div>{n.description}</div>
                                {n.details && <pre>{n.details}</pre>}
                            </div>
                        )}
                    </article>
                </div>
            </div>
        </div>
    );
}

interface NotConnectedAppMenuProps {
    title: string;
}

export function NotConnectedAppMenu({
                                        title,
                                    }: NotConnectedAppMenuProps): VNode {
    const [mobileOpen, setMobileOpen] = useState(false);

    useEffect(() => {
        document.title = `Taler Backoffice: ${title}`;
    }, [title]);

    return (
        <div
            class={mobileOpen ? "has-aside-mobile-expanded" : ""}
            onClick={() => setMobileOpen(false)}
        >
            <NavigationBar
                onMobileMenu={() => setMobileOpen(!mobileOpen)}
                title={title}
            />
        </div>
    );
}


export function NotYetReadyAppMenu({
                                       onShowSettings,
                                       title
                                   }: NotYetReadyAppMenuProps): VNode {
    const [mobileOpen, setMobileOpen] = useState(false);

    useEffect(() => {
        document.title = `Taler Backoffice: ${title}`;
    }, [title]);

    return (
        <div
            class={mobileOpen ? "has-aside-mobile-expanded" : ""}
            onClick={() => setMobileOpen(false)}
        >
            <NavigationBar
                onMobileMenu={() => setMobileOpen(!mobileOpen)}
                title={title}
            />
            (
            <Sidebar onShowSettings={onShowSettings} instance="" mobile={mobileOpen}/>
            )
        </div>
    );
}