"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AdaptableInternalApi = void 0;
const tslib_1 = require("tslib");
const PopupRedux = tslib_1.__importStar(require("../../Redux/ActionsReducers/PopupRedux"));
const InternalRedux = tslib_1.__importStar(require("../../Redux/ActionsReducers/InternalRedux"));
const ApiBase_1 = require("../Implementation/ApiBase");
const StringExtensions_1 = tslib_1.__importDefault(require("../../Utilities/Extensions/StringExtensions"));
const GeneralConstants_1 = require("../../Utilities/Constants/GeneralConstants");
const waitForCondition_1 = require("../../Utilities/waitForCondition");
const Icon_1 = require("../../components/Icon");
class AdaptableInternalApi extends ApiBase_1.ApiBase {
    getInternalState() {
        return this.getAdaptableState().Internal;
    }
    getAdaptableJSXElement() {
        return this._adaptable._PRIVATE_adaptableJSXElement ?? null;
    }
    // Popup Redux Actions
    showPopupConfirmation(confirmation) {
        this.dispatchAction(PopupRedux.PopupShowConfirmation(confirmation));
    }
    showPopupScreen(module, componentName, popupParams, popupProps) {
        this.dispatchAction(PopupRedux.PopupShowScreen(module, componentName, popupParams, popupProps));
    }
    showPopupForm(config) {
        this.dispatchAction(PopupRedux.PopupShowForm(config));
    }
    showPopupWindow({ id, title, icon, popupProps, factoryId, }) {
        this.dispatchAction(PopupRedux.PopupShowWindow({
            Id: id,
            Title: title,
            Icon: icon,
            PopupProps: popupProps,
            FactoryId: factoryId,
        }));
    }
    hidePopupScreen() {
        this.dispatchAction(PopupRedux.PopupHideScreen());
    }
    setSettingsPanelItems(menuItems) {
        this.dispatchAction(InternalRedux.SetSettingsPanelItems(menuItems));
    }
    setDashboardModuleButtons(menuItems) {
        this.dispatchAction(InternalRedux.SetDasboardModuleButtons(menuItems));
    }
    getToolbarTitle() {
        let toolbarTitle = this.getDashboardApi().getDashboardState().DashboardTitle;
        if (StringExtensions_1.default.IsNullOrEmpty(toolbarTitle)) {
            toolbarTitle = this.getOptions().adaptableId;
            if (toolbarTitle == GeneralConstants_1.ADAPTABLE_ID) {
                toolbarTitle = 'Adaptable ';
            }
        }
        return toolbarTitle;
    }
    buildCellDataChangedInfo(config) {
        return {
            ...config,
            rowData: config.rowNode?.data,
            changedAt: Date.now(),
        };
    }
    buildRowDataChangedInfo(dataRows, rowNodes, rowTrigger) {
        const rowDataChangedInfo = {
            changedAt: Date.now(),
            rowTrigger,
            dataRows,
            rowNodes,
        };
        return rowDataChangedInfo;
    }
    getAdaptableInstance() {
        return this._adaptable;
    }
    getAgGridAdapter() {
        return this._adaptable.agGridAdapter;
    }
    getInitialState() {
        return this.getOptions().initialState;
    }
    getState() {
        return this.getAdaptableState();
    }
    getValidationService() {
        return this._adaptable.ValidationService;
    }
    getModuleService() {
        return this._adaptable.ModuleService;
    }
    getDataService() {
        return this._adaptable.DataService;
    }
    getAnnotationsService() {
        return this._adaptable.AnnotationsService;
    }
    getCalculatedColumnExpressionService() {
        return this._adaptable.CalculatedColumnExpressionService;
    }
    getQueryLanguageService() {
        return this._adaptable.QueryLanguageService;
    }
    getAlertService() {
        return this._adaptable.AlertService;
    }
    getTeamSharingService() {
        return this._adaptable.TeamSharingService;
    }
    getMetamodelService() {
        return this._adaptable.MetamodelService;
    }
    getRowFormService() {
        return this._adaptable.RowFormService;
    }
    getFdc3Service() {
        return this._adaptable.Fdc3Service;
    }
    getFlashingCellService() {
        return this._adaptable.FlashingCellService;
    }
    getModules() {
        return this._adaptable.adaptableModules;
    }
    forAllRowNodesDo(func, config) {
        this._adaptable.forAllRowNodesDo(func, config);
    }
    forAllVisibleRowNodesDo(func, config) {
        this._adaptable.forAllVisibleRowNodesDo(func, config);
    }
    getLabelForButton(button, context) {
        if (!button.label) {
            return '';
        }
        if (button.label != null && typeof button.label === 'function') {
            return button.label(button, context);
        }
        else {
            return button.label;
        }
    }
    getTooltipForButton(button, context) {
        if (!button.tooltip) {
            return '';
        }
        if (button.tooltip != null && typeof button.tooltip === 'function') {
            return button.tooltip(button, context);
        }
        else {
            return button.tooltip;
        }
    }
    getStyleForButton(button, context) {
        if (!button.buttonStyle) {
            return undefined;
        }
        if (button.buttonStyle != null && typeof button.buttonStyle === 'function') {
            return button.buttonStyle(button, context);
        }
        else {
            return button.buttonStyle;
        }
    }
    getIconForButton(button, context, defaultWidthHeight) {
        if (!button.icon) {
            return;
        }
        let buttonIcon;
        if (button.icon != null && typeof button.icon === 'function') {
            buttonIcon = button.icon(button, context);
        }
        else {
            buttonIcon = button.icon;
        }
        if (!buttonIcon) {
            return;
        }
        if ((0, Icon_1.isAdaptableSystemIcon)(buttonIcon) || (0, Icon_1.isAdaptableCustomIcon)(buttonIcon)) {
            const defaultIconWidth = defaultWidthHeight?.width ?? 'var(--ab-cmp-simple-button__width)';
            const defaultIconHeight = defaultWidthHeight?.height ?? 'var(--ab-cmp-simple-button__height)';
            const buttonIconStyle = Object.assign({}, { width: defaultIconWidth, height: defaultIconHeight }, buttonIcon.style);
            buttonIcon.style = buttonIconStyle;
        }
        return buttonIcon;
    }
    isDocumentationLinksDisplayed() {
        return this.getUserInterfaceOptions().showDocumentationLinks;
    }
    // the row data which is used to preview the expression evaluation (usually the first row data)
    getQueryPreviewData() {
        const firstRowNode = this.getGridApi().getFirstRowNode();
        if (firstRowNode == undefined) {
            return {};
        }
        const firstRowData = firstRowNode?.data ? { ...firstRowNode?.data } : {};
        // handle CalcCols which are not persisted in the rowModel
        this.getCalculatedColumnApi()
            .getCalculatedColumns()
            .forEach((calculatedColumn) => {
            const columnRawValue = this._adaptable.api.gridApi.getRawValueFromRowNode(firstRowNode, calculatedColumn.ColumnId);
            firstRowData[calculatedColumn.ColumnId] = columnRawValue;
        });
        // handle FreeTextCols which are not persisted in the rowModel
        this.getFreeTextColumnApi()
            .getFreeTextColumns()
            .forEach((freeTextColumn) => {
            const columnRawValue = this.getGridApi().getRawValueFromRowNode(firstRowNode, freeTextColumn.ColumnId);
            firstRowData[freeTextColumn.ColumnId] = columnRawValue;
        });
        return firstRowData;
    }
    createFrameworkComponent(containerDomNode, frameworkComponent, componentType) {
        const createComponentFn = () => 
        // delegate the logic to framework wrapper
        this._adaptable._emitSync('FrameworkComponentChange', {
            command: 'create',
            containerDomNode,
            frameworkComponent,
            componentType,
        });
        if (this.isAdapTableReady()) {
            createComponentFn();
        }
        else {
            // adaptable may not be initialized yet if the framework component is part of the initial render
            // AFL 2021.10.14 - not really sure if this is necessary anymore?! (see the other changes in this commit)
            (0, waitForCondition_1.waitForCondition)(() => this.isAdapTableReady()).then(() => {
                createComponentFn();
            });
        }
    }
    destroyFrameworkComponent(containerDomNode, frameworkComponent, componentType) {
        this._adaptable._emitSync('FrameworkComponentChange', {
            command: 'destroy',
            containerDomNode,
            frameworkComponent,
            componentType,
        });
    }
    initializeDataChangeHistory() {
        if (this.getDataChangeHistoryOptions().activeByDefault) {
            this.dispatchAction(InternalRedux.DataChangeHistoryEnable());
        }
        else {
            this.dispatchAction(InternalRedux.DataChangeHistoryDisable());
        }
    }
    executeWithProgressIndicator(label, executeFn, errorHandlingFn) {
        this.getUserInterfaceApi().showProgressIndicator({ text: label, delay: 300 });
        // setTimeout required to give the ProgressIndicator rendering a head-start (see RAF in ProgressIndicator implementation)
        setTimeout(() => {
            try {
                executeFn();
            }
            catch (error) {
                errorHandlingFn?.();
                this.getUserInterfaceApi().hideProgressIndicator();
                this.logError('Unexpected error while executing a function with a progress indicator', error);
            }
        }, 16);
    }
    getCorrectEnglishVariant(wordToSpell) {
        if (wordToSpell.includes('our')) {
            return this.getUserInterfaceOptions().englishVariant == 'GB'
                ? wordToSpell
                : wordToSpell.replace('our', 'or');
        }
        return wordToSpell;
    }
    shouldDisplayTagSections() {
        return this.getAvailableTags() != undefined;
    }
    getAvailableTags() {
        const layoutTags = this.getLayoutTags();
        const objectTags = this.getObjectTags();
        if (!layoutTags && !objectTags) {
            return;
        }
        return [...(layoutTags || []), ...(objectTags || [])];
    }
    getObjectTags() {
        const userInterfaceOptions = this.getUserInterfaceOptions();
        if (!this.getUserInterfaceOptions().objectTags) {
            return;
        }
        if (Array.isArray(userInterfaceOptions.objectTags)) {
            return userInterfaceOptions.objectTags;
        }
        if (typeof userInterfaceOptions.objectTags === 'function') {
            // sanitize the provided tags, just to be sure that the user does NOT break the UI
            return userInterfaceOptions
                .objectTags(this.buildBaseContext())
                .filter((tag) => typeof tag === 'string');
        }
    }
    getLayoutTags() {
        const layoutOptions = this.getLayoutOptions();
        if (!layoutOptions.layoutTagOptions?.autoGenerateTagsForLayouts) {
            return;
        }
        if (layoutOptions.layoutTagOptions.autoGenerateTagsForLayouts === true) {
            return this.getLayoutApi()
                .getLayouts()
                .map((layout) => {
                return layout.Name;
            });
        }
        if (typeof layoutOptions.layoutTagOptions.autoGenerateTagsForLayouts === 'function') {
            const autoGenerateTagsForLayoutsContext = {
                layouts: this.getLayoutApi().getLayouts(),
                objectTags: this.getUserInterfaceApi().getAdaptableObjectTags(),
                ...this.buildBaseContext(),
            };
            const customGeneratedTags = layoutOptions.layoutTagOptions.autoGenerateTagsForLayouts(autoGenerateTagsForLayoutsContext);
            // sanitize the provided tags, just to be sure that the user does NOT break the UI
            return customGeneratedTags.filter((tag) => typeof tag === 'string');
        }
    }
    // General way to get to store from inside Adaptable...
    dispatchReduxAction(action) {
        this.dispatchAction(action);
    }
    // doing it this way to avoid having to expose Module Params which is internal
    showSettingsPanel(module, moduleParams) {
        this.showModulePopup(module, moduleParams);
    }
    getLabelForTag(adaptableObjectTag) {
        // not very interesting right now, but useful later when tag is not only a plain string
        return adaptableObjectTag;
    }
    getValueForTag(adaptableObjectTag) {
        // not very interesting right now, but useful later when tag is not only a plain string
        return adaptableObjectTag;
    }
    getAdaptableQueryExpressionText(query) {
        if (!query) {
            return '';
        }
        const displayColumnFriendlyNames = this.getExpressionOptions()?.displayColumnFriendlyNamesForExpressions;
        return displayColumnFriendlyNames
            ? this.getExpressionApi().getAdaptableQueryExpressionWithColumnFriendlyNames(query)
            : this.getExpressionApi().getAdaptableQueryExpression(query);
    }
    /**
     * Gets a value from a rowData object using a field name.
     * Supports deep values (e.g. fieldName = 'address.street')
     */
    // "borrowed" from https://github.com/ag-grid/ag-grid/blob/v28.2.1/community-modules/core/src/ts/utils/object.ts#L205
    getValueUsingField(rowData, fieldName) {
        if (!rowData || !fieldName?.length) {
            return;
        }
        const isColumnValueKeyNested = fieldName?.includes('.');
        // if no '.', then it's not a deep value
        if (!isColumnValueKeyNested) {
            return rowData[fieldName];
        }
        // otherwise it is a deep value, so need to dig for it
        const fields = fieldName.split('.');
        let currentObject = rowData;
        for (let i = 0; i < fields.length; i++) {
            if (currentObject == null) {
                return undefined;
            }
            currentObject = currentObject[fields[i]];
        }
        return currentObject;
    }
    /**
     * Sets a value in a rowData object using a field name.
     * Supports deep values (e.g. fieldName = 'address.street')
     */
    // "borrowed" from https://github.com/ag-grid/ag-grid/blob/v28.2.1/community-modules/core/src/ts/valueService/valueService.ts#L236
    setValueUsingField(rowData, fieldName, newValue) {
        if (!rowData || !fieldName?.length) {
            return;
        }
        const isColumnValueKeyContainsDots = fieldName?.includes('.');
        let valuesAreSame = false;
        if (!isColumnValueKeyContainsDots) {
            // soft comparison to match strings and numbers
            valuesAreSame = rowData[fieldName] == newValue;
            if (!valuesAreSame) {
                rowData[fieldName] = newValue;
            }
        }
        else {
            // otherwise it is a deep value, so need to dig for it
            const fieldPieces = fieldName.split('.');
            let currentObject = rowData;
            while (fieldPieces.length > 0 && currentObject) {
                const fieldPiece = fieldPieces.shift();
                if (fieldPieces.length === 0) {
                    // soft comparison to match strings and numbers
                    valuesAreSame = currentObject[fieldPiece] == newValue;
                    if (!valuesAreSame) {
                        currentObject[fieldPiece] = newValue;
                    }
                }
                else {
                    // NOTE AFL: this was NOT in the original AG Grid code, but we need it to handle inserting deep values (the original implementation only handled updating)
                    if (currentObject[fieldPiece] == null) {
                        currentObject[fieldPiece] = {};
                    }
                    currentObject = currentObject[fieldPiece];
                }
            }
        }
        return rowData;
    }
    findAdaptableObjectsByLookupCriteria({ scope, tag, ids }, specificAdaptableObjects) {
        if (!ids?.length && !tag && !scope) {
            return [];
        }
        let locatedAdaptableObjects = [...specificAdaptableObjects];
        // IDs are the most specific locators
        if (ids?.length) {
            locatedAdaptableObjects = locatedAdaptableObjects.filter((adaptableObject) => ids.includes(adaptableObject.Uuid));
        }
        // secondly filter by Tags
        if (tag) {
            locatedAdaptableObjects = locatedAdaptableObjects.filter((adaptableObject) => adaptableObject.Tags?.includes(tag));
        }
        // lastly filter by scope
        if (scope) {
            locatedAdaptableObjects = locatedAdaptableObjects.filter((adaptableObject) => this.getColumnScopeApi().isScopeInScope(adaptableObject.Scope, scope));
        }
        return locatedAdaptableObjects;
    }
    buildBaseContext() {
        const optionsApi = this.getOptionsApi();
        return {
            adaptableApi: this.getAdaptableApi(),
            adaptableId: optionsApi.getAdaptableId(),
            adaptableStateKey: optionsApi.getAdaptableStateKey(),
            userName: optionsApi.getUserName(),
            adaptableContext: optionsApi.getAdaptableContext(),
            clientTimestamp: new Date(),
        };
    }
    setCellSummaryInfo(cellSummaryInfo) {
        this.dispatchAction(InternalRedux.SetCellSummaryInfo(cellSummaryInfo));
    }
}
exports.AdaptableInternalApi = AdaptableInternalApi;
