/*---------------------------------------------------------------------------------------------
 * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
 * See LICENSE.md in the project root for license terms and full copyright notice.
 *--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module Settings
 */
import "./QuantityFormat.scss";
import * as React from "react";
import { DeepCompare } from "@itwin/core-geometry";
import { getQuantityTypeKey, IModelApp, QuantityType, } from "@itwin/core-frontend";
import { FormatSample, QuantityFormatPanel, } from "@itwin/imodel-components-react";
import { Listbox, ListboxItem, useSaveBeforeActivatingNewSettingsTab, useSaveBeforeClosingSettingsContainer, } from "@itwin/core-react";
import { UiFramework } from "../../UiFramework.js";
import { UnitSystemSelector } from "./UnitSystemSelector.js";
import { Button, Dialog } from "@itwin/itwinui-react";
import { SvgMeasure } from "@itwin/itwinui-icons-react";
import { useTranslation } from "../../hooks/useTranslation.js";
function formatAreEqual(obj1, obj2) {
    const compare = new DeepCompare();
    return compare.compare(obj1, obj2);
}
/**
 * Return a SettingsTabEntry that can be used to define the available settings that can be set for an application.
 * @param itemPriority - Used to define the order of the entry in the Settings Stage
 * @param opts - Options to initialize the settings page that allows users to set Quantity formatting overrides.
 * @beta
 */
export function getQuantityFormatsSettingsManagerEntry(itemPriority, opts) {
    const { availableUnitSystems, initialQuantityType } = { ...opts };
    return {
        itemPriority,
        tabId: "uifw:Quantity",
        label: UiFramework.translate("settings.quantity-formatting.label"),
        subLabel: UiFramework.translate("settings.quantity-formatting.subLabel"),
        page: (React.createElement(QuantityFormatSettingsPage, { initialQuantityType: initialQuantityType ?? QuantityType.Length, availableUnitSystems: availableUnitSystems ??
                new Set(["metric", "imperial", "usCustomary", "usSurvey"]) })),
        isDisabled: false,
        icon: React.createElement(SvgMeasure, null),
        tooltip: UiFramework.translate("settings.quantity-formatting.tooltip"),
        pageWillHandleCloseRequest: true,
    };
}
/** UI Component shown in settings page to set the active Presentation Unit System and to set format overrides.
 * @beta
 */
export function QuantityFormatSettingsPage({ initialQuantityType, availableUnitSystems, }) {
    const { translate } = useTranslation();
    const [activeUnitSystemKey, setActiveUnitSystemKey] = React.useState(IModelApp.quantityFormatter.activeUnitSystem);
    const [activeQuantityType, setActiveQuantityType] = React.useState(getQuantityTypeKey(initialQuantityType));
    const [activeFormatterSpec, setActiveFormatterSpec] = React.useState(IModelApp.quantityFormatter.findFormatterSpecByQuantityType(getQuantityTypeKey(activeQuantityType)));
    const [saveEnabled, setSaveEnabled] = React.useState(false);
    const [clearEnabled, setClearEnabled] = React.useState(IModelApp.quantityFormatter.hasActiveOverride(initialQuantityType, true));
    const newQuantityTypeRef = React.useRef(undefined);
    React.useEffect(() => {
        return IModelApp.quantityFormatter.onActiveFormattingUnitSystemChanged.addListener(() => {
            if (activeUnitSystemKey !== IModelApp.quantityFormatter.activeUnitSystem) {
                setActiveUnitSystemKey(IModelApp.quantityFormatter.activeUnitSystem);
                setActiveFormatterSpec(IModelApp.quantityFormatter.findFormatterSpecByQuantityType(activeQuantityType));
                setSaveEnabled(false);
                setClearEnabled(IModelApp.quantityFormatter.hasActiveOverride(activeQuantityType, true));
            }
        });
    }, [activeQuantityType, activeUnitSystemKey]);
    React.useEffect(() => {
        return IModelApp.quantityFormatter.onQuantityFormatsChanged.addListener((args) => {
            if (!newQuantityTypeRef.current) {
                const quantityKey = IModelApp.quantityFormatter.getQuantityTypeKey(activeQuantityType);
                if (args.quantityType === quantityKey) {
                    setActiveFormatterSpec(IModelApp.quantityFormatter.findFormatterSpecByQuantityType(activeQuantityType));
                    setSaveEnabled(false);
                    setClearEnabled(IModelApp.quantityFormatter.hasActiveOverride(activeQuantityType, true));
                }
            }
            newQuantityTypeRef.current = undefined;
        });
    }, [activeQuantityType]);
    const saveChanges = React.useCallback((afterSaveFunction, args) => {
        if (activeFormatterSpec) {
            const formatProps = activeFormatterSpec.format.toJSON();
            const formatPropsInUse = IModelApp.quantityFormatter
                .findFormatterSpecByQuantityType(activeQuantityType)
                .format.toJSON();
            if (formatPropsInUse &&
                !formatAreEqual(formatProps, formatPropsInUse)) {
                UiFramework.dialogs.modal.open(React.createElement(SaveFormatModalDialog, { formatProps: formatProps, quantityType: activeQuantityType, onDialogCloseArgs: args, onDialogClose: afterSaveFunction }), "saveQuantityFormat");
                return;
            }
        }
        afterSaveFunction(args);
    }, [activeFormatterSpec, activeQuantityType]);
    // eslint-disable-next-line @typescript-eslint/no-deprecated
    useSaveBeforeActivatingNewSettingsTab(UiFramework.settingsManager, saveChanges);
    // eslint-disable-next-line @typescript-eslint/no-deprecated
    useSaveBeforeClosingSettingsContainer(UiFramework.settingsManager, saveChanges);
    const processListboxValueChange = React.useCallback((newQuantityType) => {
        const volumeFormatterSpec = IModelApp.quantityFormatter.findFormatterSpecByQuantityType(newQuantityType);
        setActiveFormatterSpec(volumeFormatterSpec);
        setActiveQuantityType(newQuantityType);
        setSaveEnabled(false);
        setClearEnabled(IModelApp.quantityFormatter.hasActiveOverride(newQuantityType, true));
    }, []);
    const onListboxValueChange = React.useCallback((newQuantityType) => {
        if (activeFormatterSpec) {
            const formatProps = activeFormatterSpec.format.toJSON();
            const formatPropsInUse = IModelApp.quantityFormatter
                .findFormatterSpecByQuantityType(activeQuantityType)
                .format.toJSON();
            if (formatPropsInUse &&
                !formatAreEqual(formatProps, formatPropsInUse)) {
                newQuantityTypeRef.current = newQuantityType;
                UiFramework.dialogs.modal.open(React.createElement(SaveFormatModalDialog, { formatProps: formatProps, quantityType: activeQuantityType, onDialogCloseArgs: newQuantityType, onDialogClose: processListboxValueChange }), "saveQuantityFormat");
                return;
            }
        }
        processListboxValueChange(newQuantityType);
    }, [activeFormatterSpec, activeQuantityType, processListboxValueChange]);
    const handleOnFormatChanged = React.useCallback(async (formatProps) => {
        if (activeFormatterSpec) {
            const newSpec = await IModelApp.quantityFormatter.generateFormatterSpecByType(activeQuantityType, formatProps);
            const formatPropsInUse = IModelApp.quantityFormatter.getFormatPropsByQuantityType(activeQuantityType);
            if (formatPropsInUse)
                setSaveEnabled(!formatAreEqual(formatProps, formatPropsInUse));
            setActiveFormatterSpec(newSpec);
        }
    }, [activeFormatterSpec, activeQuantityType]);
    const handleOnFormatSave = React.useCallback(async () => {
        if (activeFormatterSpec) {
            const format = activeFormatterSpec.format.toJSON();
            await IModelApp.quantityFormatter.setOverrideFormat(activeQuantityType, format);
            setClearEnabled(true);
        }
    }, [activeFormatterSpec, activeQuantityType]);
    const handleOnFormatReset = React.useCallback(async () => {
        await IModelApp.quantityFormatter.clearOverrideFormats(activeQuantityType);
        setClearEnabled(false);
    }, [activeQuantityType]);
    const processNewUnitSystem = React.useCallback(async (unitSystem) => {
        await IModelApp.quantityFormatter.setActiveUnitSystem(unitSystem);
    }, []);
    const handleUnitSystemSelected = React.useCallback(async (unitSystem) => {
        if (unitSystem === activeUnitSystemKey)
            return;
        saveChanges(processNewUnitSystem, unitSystem);
    }, [activeUnitSystemKey, processNewUnitSystem, saveChanges]);
    return (React.createElement("div", { className: "quantity-formatting-container" },
        React.createElement(UnitSystemSelector, { selectedUnitSystemKey: activeUnitSystemKey, availableUnitSystems: availableUnitSystems, onUnitSystemSelected: handleUnitSystemSelected }),
        React.createElement("span", { className: "uifw-quantity-format-section-label" }, translate("settings.quantity-formatting.formatSectionLabel")),
        React.createElement("div", { className: "uifw-quantity-types-container" },
            React.createElement("div", { className: "left-panel" },
                React.createElement(Listbox, { id: "uifw-quantity-types-list", className: "uifw-quantity-types", onListboxValueChange: onListboxValueChange, selectedValue: activeQuantityType }, [...IModelApp.quantityFormatter.quantityTypesRegistry.keys()].map((key) => {
                    const entry = IModelApp.quantityFormatter.quantityTypesRegistry.get(key);
                    const description = entry.description;
                    const label = entry.label;
                    return (
                    // eslint-disable-next-line @typescript-eslint/no-deprecated
                    React.createElement(ListboxItem, { key: entry.key, className: "quantity-type-list-entry", value: entry.key },
                        React.createElement("span", { className: "map-source-list-entry-name", title: description }, label)));
                }))),
            React.createElement("div", { className: "right-panel" }, activeFormatterSpec && (React.createElement(React.Fragment, null,
                React.createElement("div", { className: "uifw-quantity-types-right-top" },
                    React.createElement("div", { className: "uifw-quantity-types-right-top-sample" },
                        React.createElement(FormatSample, { formatSpec: activeFormatterSpec, initialMagnitude: 1234.56, hideLabels: true }))),
                React.createElement("div", { className: "uifw-quantity-types-formats" },
                    React.createElement(QuantityFormatPanel, { onFormatChange: handleOnFormatChanged, quantityType: activeQuantityType })),
                React.createElement("div", { className: "components-button-panel" },
                    React.createElement(Button, { styleType: "cta", onClick: handleOnFormatSave, disabled: !saveEnabled }, translate("settings.quantity-formatting.setButtonLabel")),
                    React.createElement(Button, { styleType: "default", onClick: handleOnFormatReset, disabled: !clearEnabled }, translate("settings.quantity-formatting.clearButtonLabel")))))))));
}
function SaveFormatModalDialog({ formatProps, quantityType, onDialogCloseArgs, onDialogClose, }) {
    const { translate } = useTranslation();
    const [isOpen, setIsOpen] = React.useState(true);
    const handleClose = React.useCallback(() => {
        setIsOpen(false);
        UiFramework.dialogs.modal.close();
        onDialogClose && onDialogClose(onDialogCloseArgs);
    }, [onDialogClose, onDialogCloseArgs]);
    const handleOK = React.useCallback(() => {
        void IModelApp.quantityFormatter.setOverrideFormat(quantityType, formatProps);
        handleClose();
    }, [formatProps, handleClose, quantityType]);
    const handleCancel = React.useCallback(() => {
        handleClose();
    }, [handleClose]);
    return (React.createElement(Dialog, { isOpen: isOpen, onClose: handleCancel, className: "uifw-settings-quantityFormatting-saveFormatModalDialog", closeOnEsc: true, closeOnExternalClick: true, preventDocumentScroll: true },
        React.createElement(Dialog.Backdrop, null),
        React.createElement(Dialog.Main, { style: { minWidth: 200, maxWidth: 400, minHeight: 150, maxHeight: 400 } },
            React.createElement(Dialog.TitleBar, { titleText: "Save Format Changes" }),
            React.createElement(Dialog.Content, null, "Do you want to save changes to format before changing to another type?"),
            React.createElement(Dialog.ButtonBar, null,
                React.createElement(Button, { styleType: "high-visibility", onClick: handleOK }, translate("dialog.yes")),
                React.createElement(Button, { onClick: handleCancel }, translate("dialog.no"))))));
}
//# sourceMappingURL=QuantityFormat.js.map