"use strict";
/*---------------------------------------------------------------------------------------------
 * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
 * See LICENSE.md in the project root for license terms and full copyright notice.
 *--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module UiProvider
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.ComponentGenerator = void 0;
require("./DefaultDialogGridContainer.scss");
const classnames_1 = require("classnames");
const React = require("react");
const appui_abstract_1 = require("@itwin/appui-abstract");
const components_react_1 = require("@itwin/components-react");
const core_bentley_1 = require("@itwin/core-bentley");
const itwinui_react_1 = require("@itwin/itwinui-react");
function EditorLabel({ uiDataProvider, item, isLeftmostRecord, }) {
    const [isDisabled, setIsDisabled] = React.useState(!!item.isDisabled);
    const displayLabel = React.useMemo(() => {
        return item.property.displayLabel || item.property.name;
    }, [item]);
    // listen for tool sync property events and update the isDisabled state
    React.useEffect(() => {
        return uiDataProvider.onSyncPropertiesChangeEvent.addListener((args) => {
            const mySyncItem = args.properties.find((syncItem) => syncItem.propertyName === item.property.name);
            if (mySyncItem) {
                setIsDisabled(!!mySyncItem.isDisabled);
            }
        });
    }, [uiDataProvider, item]);
    const className = (0, classnames_1.default)("uifw-default-label", !!isLeftmostRecord && "uifw-default-narrow-only-display");
    return (React.createElement(itwinui_react_1.Label, { className: className, htmlFor: item.property.name, disabled: isDisabled },
        displayLabel,
        ":"));
}
function PropertyEditor({ uiDataProvider, initialItem, isLock, setFocus, onCancel, }) {
    const getLatestRecordValue = React.useCallback(() => {
        let newRecord = appui_abstract_1.UiLayoutDataProvider.getPropertyRecord(initialItem);
        const foundItem = isLock
            ? uiDataProvider.items.find((item) => item.lockProperty?.property.name === initialItem.property.name)
            : uiDataProvider.items.find((item) => item.property.name === initialItem.property.name);
        if (foundItem) {
            if (isLock) {
                newRecord = newRecord.copyWithNewValue({
                    value: foundItem.lockProperty.value.value,
                    valueFormat: appui_abstract_1.PropertyValueFormat.Primitive,
                });
                newRecord.isDisabled = foundItem.lockProperty.isDisabled;
            }
            else {
                newRecord = newRecord.copyWithNewValue({
                    value: foundItem.value.value,
                    valueFormat: appui_abstract_1.PropertyValueFormat.Primitive,
                });
                newRecord.isDisabled = foundItem.isDisabled;
            }
        }
        return newRecord;
    }, [initialItem, isLock, uiDataProvider.items]);
    const currentRecord = getLatestRecordValue();
    const [propertyRecord, setPropertyRecord] = React.useState(currentRecord);
    // monitor tool for sync UI events
    React.useEffect(() => {
        const handleSync = (args) => {
            const mySyncItem = args.properties.find((syncItem) => syncItem.propertyName === initialItem.property.name);
            if (mySyncItem) {
                const newPropertyValue = propertyRecord.copyWithNewValue({
                    value: mySyncItem.value.value,
                    valueFormat: appui_abstract_1.PropertyValueFormat.Primitive,
                    displayValue: mySyncItem.value.displayValue,
                }, mySyncItem.property);
                if (mySyncItem.property) {
                    if (mySyncItem.property.name === mySyncItem.propertyName) {
                        newPropertyValue.isDisabled = mySyncItem.isDisabled;
                        setPropertyRecord(newPropertyValue);
                    }
                    else {
                        core_bentley_1.Logger.logError("PropertyEditor", `Error trying to replace propertyName=${mySyncItem.propertyName} with property named ${mySyncItem.property.name}`);
                    }
                }
                else {
                    newPropertyValue.isDisabled = mySyncItem.isDisabled;
                    setPropertyRecord(newPropertyValue);
                }
            }
        };
        uiDataProvider.onSyncPropertiesChangeEvent.addListener(handleSync);
        return () => {
            uiDataProvider.onSyncPropertiesChangeEvent.removeListener(handleSync);
        };
    }, [uiDataProvider, propertyRecord, initialItem.property.name]);
    const className = React.useMemo(() => (isLock ? "uifw-default-property-lock" : "uifw-default-editor"), [isLock]);
    const handleCommit = React.useCallback((commit) => {
        // UiLayoutDataProvider supports only primitive property types
        (0, core_bentley_1.assert)(commit.newValue.valueFormat === appui_abstract_1.PropertyValueFormat.Primitive &&
            commit.propertyRecord.value.valueFormat ===
                appui_abstract_1.PropertyValueFormat.Primitive);
        const newPropertyValue = propertyRecord.copyWithNewValue(commit.newValue);
        const syncItem = {
            value: commit.newValue,
            propertyName: initialItem.property.name,
            isDisabled: newPropertyValue.isDisabled,
        };
        uiDataProvider.applyUiPropertyChange(syncItem);
        // Now have the uiDataProvider refetch the latest property values from the tool
        uiDataProvider.reloadDialogItems(true);
    }, [initialItem.property.name, propertyRecord, uiDataProvider]);
    const handleCancel = () => { };
    return (React.createElement("div", { key: initialItem.property.name, className: className },
        React.createElement(components_react_1.EditorContainer, { key: initialItem.property.name, propertyRecord: propertyRecord, setFocus: setFocus, onCommit: handleCommit, onCancel: onCancel ?? handleCancel })));
}
/** Utility methods to generate react ui from DialogRow specs
 * @internal
 */
class ComponentGenerator {
    constructor(_uiDataProvider, _onCancel) {
        this._uiDataProvider = _uiDataProvider;
        this._onCancel = _onCancel;
    }
    get uiDataProvider() {
        return this._uiDataProvider;
    }
    getEditor(item, isLock = false, setFocus = false) {
        return (React.createElement(PropertyEditor, { key: item.property.name, uiDataProvider: this.uiDataProvider, initialItem: item, isLock: isLock, setFocus: setFocus, onCancel: this._onCancel }));
    }
    generateRowWithButtonGroupEditors(row, rowIndex) {
        if (1 === row.items.length) {
            return (React.createElement("div", { key: row.items[0].property.name, className: "uifw-default-inline-editor-group uifw-default-center-across-width" }, this.getEditor(row.items[0])));
        }
        return (React.createElement("div", { key: rowIndex, className: "uifw-default-inline-editor-group uifw-default-center-across-width" },
            React.createElement("div", { className: "uifw-default-inline-editor-group" }, row.items.map((item) => this.getEditor(item)))));
    }
    generateEntryWithButtonGroupEditors(row, rowIndex) {
        if (1 === row.items.length) {
            return {
                labelNode: "",
                editorNode: (React.createElement("div", { key: row.items[0].property.name, className: "uifw-default-inline-editor-group uifw-default-center-across-width" }, this.getEditor(row.items[0]))),
            };
        }
        return {
            labelNode: "",
            editorNode: (React.createElement("div", { key: rowIndex, className: "uifw-default-inline-editor-group uifw-default-center-across-width" },
                React.createElement("div", { className: "uifw-default-inline-editor-group" }, row.items.map((item) => this.getEditor(item))))),
        };
    }
    getEditorLabel(item, isLeftmostRecord = false) {
        return (React.createElement(EditorLabel, { uiDataProvider: this.uiDataProvider, item: item, isLeftmostRecord: isLeftmostRecord }));
    }
    getLeftLockAndLabel(rowItem, multiplePropertiesOnRow) {
        const record = appui_abstract_1.UiLayoutDataProvider.getPropertyRecord(rowItem);
        const lockEditor = appui_abstract_1.UiLayoutDataProvider.hasAssociatedLockProperty(rowItem)
            ? this.getEditor(rowItem.lockProperty, true)
            : null;
        const label = appui_abstract_1.UiLayoutDataProvider.editorWantsLabel(rowItem)
            ? this.getEditorLabel(rowItem)
            : null;
        const classNames = multiplePropertiesOnRow
            ? "uifw-default-lock-and-label uifw-default-wide-only-display"
            : "uifw-default-lock-and-label";
        return (React.createElement("div", { key: `lock-${record.property.name}`, className: classNames },
            lockEditor,
            label));
    }
    getInlineLabelAndEditor(item, isLeftmostRecord) {
        const label = appui_abstract_1.UiLayoutDataProvider.editorWantsLabel(item)
            ? this.getEditorLabel(item, isLeftmostRecord)
            : null;
        return (React.createElement("div", { key: item.property.name, className: "uifw-default-inline-label-and-editor" },
            label,
            this.getEditor(item)));
    }
    getRowWithMultipleEditors(row) {
        return (React.createElement("div", { className: "uifw-default-inline-editor-group" }, row.items.map((item, index) => this.getInlineLabelAndEditor(item, index === 0))));
    }
    getDivForRow(row) {
        if (row.items.length === 1)
            return this.getEditor(row.items[0]);
        return this.getRowWithMultipleEditors(row);
    }
    getRow(row, rowIndex) {
        if (appui_abstract_1.UiLayoutDataProvider.onlyContainButtonGroupEditors(row)) {
            return this.generateRowWithButtonGroupEditors(row, rowIndex);
        }
        else {
            return (React.createElement(React.Fragment, { key: rowIndex },
                this.getLeftLockAndLabel(row.items[0], row.items.length > 1),
                this.getDivForRow(row)));
        }
    }
    getToolSettingsEntry(row, rowIndex) {
        if (appui_abstract_1.UiLayoutDataProvider.onlyContainButtonGroupEditors(row)) {
            return this.generateEntryWithButtonGroupEditors(row, rowIndex);
        }
        else {
            return {
                labelNode: this.getLeftLockAndLabel(row.items[0], row.items.length > 1),
                editorNode: this.getDivForRow(row),
            };
        }
    }
    /** ToolSettingsEntries are used by the tool settings bar. */
    getToolSettingsEntries() {
        return this.uiDataProvider.rows.map((row, index) => this.getToolSettingsEntry(row, index));
    }
}
exports.ComponentGenerator = ComponentGenerator;
//# sourceMappingURL=ComponentGenerator.js.map