"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 SystemRedux = tslib_1.__importStar(require("../../Redux/ActionsReducers/SystemRedux"));
const GridRedux = tslib_1.__importStar(require("../../Redux/ActionsReducers/GridRedux"));
const DeadRedux = tslib_1.__importStar(require("../../Redux/DeadRedux"));
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");
const uuid_1 = require("../../components/utils/uuid");
class AdaptableInternalApi extends ApiBase_1.ApiBase {
    getSystemState() {
        return this.getAdaptableState().System;
    }
    getAdaptableJSXElement() {
        var _a;
        return (_a = this._adaptable._PRIVATE_adaptableJSXElement) !== null && _a !== void 0 ? _a : null;
    }
    // Popup Redux Actions
    showPopupConfirmation(confirmation) {
        this.dispatchAction(PopupRedux.PopupShowConfirmation(confirmation));
    }
    showPopupScreen(module, componentName, popupParams, popupProps) {
        this.dispatchAction(PopupRedux.PopupShowScreen(module, componentName, popupParams, popupProps));
    }
    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(GridRedux.setSettingsPanelItems(menuItems));
    }
    setMenuModuleItems(menuItems) {
        this.dispatchAction(GridRedux.SetMenuModuleItems(menuItems));
    }
    setPivotModeOn() {
        this.dispatchAction(GridRedux.SetPivotModeOn());
    }
    setPivotModeOff() {
        this.dispatchAction(GridRedux.SetPivotModeOff());
    }
    isGridInPivotMode() {
        return this.getAdaptableState().Grid.IsGridInPivotMode;
    }
    setTreeMode(mode) {
        if (!!mode) {
            this.dispatchAction(GridRedux.SetTreeModeOn());
        }
        else {
            this.dispatchAction(GridRedux.SetTreeModeOff());
        }
    }
    isGridInTreeMode() {
        return this.getAdaptableState().Grid.IsGridInTreeMode;
    }
    getToolbarTitle() {
        let toolbarTitle = this._adaptable.api.dashboardApi.getDashboardState().DashboardTitle;
        if (StringExtensions_1.default.IsNullOrEmpty(toolbarTitle)) {
            toolbarTitle = this.getOptions().adaptableId;
            if (toolbarTitle == GeneralConstants_1.ADAPTABLE_ID) {
                toolbarTitle = 'Adaptable ';
            }
        }
        return toolbarTitle;
    }
    buildDataChangedInfo(config) {
        var _a;
        return Object.assign(Object.assign({}, config), { rowData: (_a = config.rowNode) === null || _a === void 0 ? void 0 : _a.data, changedAt: Date.now() });
    }
    getAdaptableInstance() {
        return this._adaptable;
    }
    getAgGridAdapter() {
        return this._adaptable.agGridAdapter;
    }
    getPredefinedConfig() {
        return this.getOptions().predefinedConfig;
    }
    getState() {
        return this.getAdaptableState();
    }
    getValidationService() {
        return this._adaptable.ValidationService;
    }
    getModuleService() {
        return this._adaptable.ModuleService;
    }
    getDataService() {
        return this._adaptable.DataService;
    }
    getCellPopupService() {
        return this._adaptable.CellPopupService;
    }
    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;
    }
    getRowEditService() {
        return this._adaptable.RowEditService;
    }
    getFdc3Service() {
        return this._adaptable.Fdc3Service;
    }
    getFlashingCellService() {
        return this._adaptable.FlashingCellService;
    }
    getModules() {
        return this._adaptable.adaptableModules;
    }
    getModuleFriendlyName(adaptableModule) {
        var _a, _b;
        return ((_b = (_a = this._adaptable.ModuleService.getModuleInfoByModule(adaptableModule)) === null || _a === void 0 ? void 0 : _a.FriendlyName) !== null && _b !== void 0 ? _b : adaptableModule);
    }
    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) {
        var _a, _b;
        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 = (_a = defaultWidthHeight === null || defaultWidthHeight === void 0 ? void 0 : defaultWidthHeight.width) !== null && _a !== void 0 ? _a : 'var(--ab-cmp-simple-button__width)';
            const defaultIconHeight = (_b = defaultWidthHeight === null || defaultWidthHeight === void 0 ? void 0 : defaultWidthHeight.height) !== null && _b !== void 0 ? _b : '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() {
        var _a;
        const firstRowNode = this._adaptable.api.gridApi.getFirstRowNode();
        if (firstRowNode == undefined) {
            return {};
        }
        const firstRowData = (_a = Object.assign({}, firstRowNode === null || firstRowNode === void 0 ? void 0 : firstRowNode.data)) !== null && _a !== void 0 ? _a : {};
        // handle CalcCols which are not persisted in the rowModel
        this._adaptable.api.calculatedColumnApi.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._adaptable.api.freeTextColumnApi.getFreeTextColumns().forEach((freeTextColumn) => {
            const columnRawValue = this._adaptable.api.gridApi.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(SystemRedux.SystemDataChangeHistoryEnable());
        }
        else {
            this.dispatchAction(SystemRedux.SystemDataChangeHistoryDisable());
        }
    }
    executeWithProgressIndicator(label, executeFn, errorHandlingFn) {
        this.getAdaptableApi().userInterfaceApi.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 === null || errorHandlingFn === void 0 ? void 0 : 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() {
        var _a;
        const layoutOptions = this.getLayoutOptions();
        if (!((_a = layoutOptions.layoutTagOptions) === null || _a === void 0 ? void 0 : _a.autoGenerateTagsForLayouts)) {
            return;
        }
        if (layoutOptions.layoutTagOptions.autoGenerateTagsForLayouts === true) {
            return this.getLayoutApi()
                .getLayouts()
                .map((layout) => {
                return layout.Name;
            });
        }
        if (typeof layoutOptions.layoutTagOptions.autoGenerateTagsForLayouts === 'function') {
            const autoGenerateTagsForLayoutsContext = Object.assign({ layouts: this._adaptable.api.layoutApi.getLayouts(), objectTags: this.getAdaptableApi().userInterfaceApi.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) {
        var _a;
        if (!query) {
            return '';
        }
        const displayColumnFriendlyNames = (_a = this.getExpressionOptions()) === null || _a === void 0 ? void 0 : _a.displayColumnFriendlyNamesForExpressions;
        return displayColumnFriendlyNames
            ? this._adaptable.api.expressionApi.getAdaptableQueryExpressionWithColumnFriendlyNames(query)
            : this._adaptable.api.expressionApi.getAdaptableQueryExpression(query);
    }
    deleteConditionalStyles(conditionalStyles) {
        conditionalStyles.forEach((cs) => {
            this.dispatchAction(DeadRedux.ConditionalStyleDelete(cs));
        });
    }
    persistPreviousGroupedColumnsIndex(layoutId, columnId, columnIndex) {
        this.dispatchAction(SystemRedux.SystemSetPreviousGroupedColumnsIndex(layoutId, columnId, columnIndex));
    }
    getPreviousGroupedColumnsIndex(layoutId) {
        var _a;
        return (_a = SystemRedux.SystemPreviousGroupedColumnsSelector(this.getAdaptableState().System)) === null || _a === void 0 ? void 0 : _a[layoutId];
    }
    /**
     * 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 === null || fieldName === void 0 ? void 0 : fieldName.length)) {
            return;
        }
        const isColumnValueKeyNested = fieldName === null || fieldName === void 0 ? void 0 : 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 === null || fieldName === void 0 ? void 0 : fieldName.length)) {
            return;
        }
        const isColumnValueKeyContainsDots = fieldName === null || fieldName === void 0 ? void 0 : 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 === null || ids === void 0 ? void 0 : ids.length) && !tag && !scope) {
            return [];
        }
        let locatedAdaptableObjects = [...specificAdaptableObjects];
        // IDs are the most specific locators
        if (ids === null || ids === void 0 ? void 0 : ids.length) {
            locatedAdaptableObjects = locatedAdaptableObjects.filter((adaptableObject) => ids.includes(adaptableObject.Uuid));
        }
        // secondly filter by Tags
        if (tag) {
            locatedAdaptableObjects = locatedAdaptableObjects.filter((adaptableObject) => { var _a; return (_a = adaptableObject.Tags) === null || _a === void 0 ? void 0 : _a.includes(tag); });
        }
        // lastly filter by scope
        if (scope) {
            locatedAdaptableObjects = locatedAdaptableObjects.filter((adaptableObject) => this.getColumnScopeApi().isScopeInScope(adaptableObject.Scope, scope));
        }
        return locatedAdaptableObjects;
    }
    buildBaseContext() {
        return {
            adaptableApi: this.getAdaptableApi(),
            adaptableId: this.getAdaptableApi().optionsApi.getAdaptableId(),
            userName: this.getAdaptableApi().optionsApi.getUserName(),
        };
    }
    getActionButtonsAndActionColumn(colDef) {
        var _a;
        let actionColumn;
        if (this.getColumnApi().isActionRowButtonColumn(colDef.colId)) {
            const actionButtons = this.getActionRowApi().internalApi.getActionRowButtonDefs();
            actionColumn = {
                columnId: GeneralConstants_1.ADAPTABLE_ROW_ACTION_BUTTONS,
                actionColumnButton: actionButtons,
            };
        }
        if (!actionColumn && this.getFdc3Api().internalApi.isFdc3MainActionColumn(colDef.colId)) {
            const actionButtons = this.getFdc3Api().internalApi.getButtonsForFdc3MainActionColumn();
            actionColumn = {
                columnId: this.getFdc3Options().actionColumnDefaultConfiguration.columnId,
                actionColumnButton: actionButtons,
            };
        }
        if (!actionColumn &&
            this.getFdc3Api().internalApi.isFdc3StandaloneActionColumn(colDef.colId, colDef.type)) {
            const actionButtons = this.getFdc3Api().internalApi.getButtonsForFdc3StandaloneActionColumn(colDef.colId);
            actionColumn = {
                columnId: colDef.colId,
                actionColumnButton: actionButtons,
            };
        }
        if (!actionColumn) {
            actionColumn = (_a = this._adaptable.api.actionColumnApi
                .getActionColumns()) === null || _a === void 0 ? void 0 : _a.find((ac) => ac.columnId == colDef.colId);
        }
        if (!(actionColumn === null || actionColumn === void 0 ? void 0 : actionColumn.actionColumnButton)) {
            return {
                actionButtons: [],
                actionColumn,
            };
        }
        let actionButtons = Array.isArray(actionColumn.actionColumnButton)
            ? actionColumn.actionColumnButton
            : [actionColumn.actionColumnButton];
        // actionButtons don't have IDs, so we need to generate them to be used later as a react component key
        actionButtons = actionButtons.map((actionButton) => (Object.assign(Object.assign({}, actionButton), { Uuid: (0, uuid_1.createUuid)() })));
        return { actionButtons, actionColumn };
    }
}
exports.AdaptableInternalApi = AdaptableInternalApi;
