"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ActionRowInternalApi = void 0;
const tslib_1 = require("tslib");
const ApiBase_1 = require("../Implementation/ApiBase");
const GeneralConstants_1 = require("../../Utilities/Constants/GeneralConstants");
const UIHelper_1 = tslib_1.__importDefault(require("../../View/UIHelper"));
const ActionColumnRenderer_1 = require("../../agGrid/ActionColumnRenderer");
class ActionRowInternalApi extends ApiBase_1.ApiBase {
    buildRowEditForm(rowNode) {
        return this.buildActionRow('rowEdited', rowNode);
    }
    buildRowCreateForm(clonedRowNode) {
        return this.buildActionRow('rowCreated', clonedRowNode);
    }
    get actionRowFormOptions() {
        return this.getActionRowOptions().actionRowFormOptions;
    }
    get adaptableInstance() {
        return this.getAdaptableInternalApi().getAdaptableInstance();
    }
    buildActionRow(type, rowNode) {
        const formFields = this.buildActionRowFields(type, rowNode);
        const formButtons = this.buidActionRowButtons(type, rowNode, formFields);
        const formTitle = this.getFormTitle(type, rowNode);
        const formDescription = this.getFormDescription(type, rowNode);
        const actionRowForm = {
            title: formTitle,
            description: formDescription,
            fields: formFields,
            buttons: formButtons,
        };
        return actionRowForm;
    }
    getFormTitle(type, rowNode) {
        if (this.actionRowFormOptions.formTitle == undefined) {
            return type === 'rowCreated' ? 'Create New Row' : 'Edit Row';
        }
        return typeof this.actionRowFormOptions.formTitle === 'function'
            ? this.actionRowFormOptions.formTitle(this.buildFormParamContext(type, rowNode))
            : this.actionRowFormOptions.formTitle;
    }
    getFormDescription(type, rowNode) {
        return typeof this.actionRowFormOptions.formDescription === 'function'
            ? this.actionRowFormOptions.formDescription(this.buildFormParamContext(type, rowNode))
            : this.actionRowFormOptions.formDescription;
    }
    buildFormParamContext(type, rowNode) {
        return Object.assign(Object.assign({ rowNode }, this.getAdaptableInternalApi().buildBaseContext()), { type: type });
    }
    buildActionRowFields(actionRowType, rowNode) {
        const relevantColumns = this.getColumnApi().getColumns()
            .filter((column) => {
            // if there is NO rowNode, do NOT display the non-editable fields as they will be empty
            return !!rowNode || this.isCellEditable(column, rowNode);
        })
            .filter((column) => !this.getColumnApi().isActionRowButtonColumn(column.columnId) &&
            this.showColumnInActionRowForm(column, actionRowType));
        return relevantColumns.map((column) => this.buildFormField(actionRowType, column, rowNode));
    }
    showColumnInActionRowForm(adaptableColumn, actionRowType) {
        const showColumnFn = this.getActionRowOptions().actionRowFormOptions.showColumninActionRowForm;
        if (typeof showColumnFn === 'function') {
            return showColumnFn(Object.assign(Object.assign({}, this.getAdaptableInternalApi().buildBaseContext()), { adaptableColumn,
                actionRowType }));
        }
        return true;
    }
    buidActionRowButtons(type, rowNode, formFields) {
        // 1. check if there are custom user provided buttons
        if (Array.isArray(this.actionRowFormOptions.formButtons)) {
            return this.actionRowFormOptions.formButtons;
        }
        // 2. else return the standard ones
        const cancelButton = {
            label: 'Cancel',
            buttonStyle: {
                variant: 'raised',
                tone: 'neutral',
            },
        };
        const saveButton = {
            label: 'Save',
            buttonStyle: {
                variant: 'raised',
                tone: 'success',
            },
            onClick: (button, context) => {
                var _a, _b;
                // textOutput should not be saved, their values are set to display values
                // we need to filter out the textOutput fields and add the primaryKey
                const eventInfo = type === 'rowCreated'
                    ? Object.assign(Object.assign({ type: 'rowCreated', formData: this.prepareCreateData(formFields, context) }, this.getAdaptableInternalApi().buildBaseContext()), { clonedRowNode: rowNode }) : Object.assign({ type: 'rowEdited', formData: this.prepareEditData(formFields, context), rowNode: rowNode }, this.getAdaptableInternalApi().buildBaseContext());
                this.getEventApi().emit('ActionRowSubmitted', eventInfo);
                (_b = (_a = this.actionRowFormOptions) === null || _a === void 0 ? void 0 : _a.onFormSubmit) === null || _b === void 0 ? void 0 : _b.call(_a, eventInfo);
            },
        };
        return [cancelButton, saveButton];
    }
    // private getNullValueForColumn(column: AdaptableColumn) {}
    prepareCreateData(formFields, context) {
        // when creating we just omit values that are not set
        const dataToSave = Object.assign({}, context.formData);
        for (const formField of formFields) {
            if (dataToSave[formField.name] === '') {
                delete dataToSave[formField.name];
            }
        }
        return dataToSave;
    }
    prepareEditData(formFields, context) {
        const dataToSave = Object.assign({}, context.formData);
        for (const formField of formFields) {
            if (formField.fieldType === 'textOutput') {
                delete dataToSave[formField.name];
            }
        }
        const pkValue = this._adaptable.getPrimaryKeyValueFromRowNode(context.rowNode);
        dataToSave[this.getOptions().primaryKey] = pkValue;
        return dataToSave;
    }
    isCellEditable(column, rowNode) {
        if (!rowNode) {
            return !column.readOnly;
        }
        const gridCell = this.getGridApi().getGridCellFromRowNode(rowNode, column.columnId);
        return this.getGridApi().isCellEditable(gridCell);
    }
    buildFormField(type, column, rowNode) {
        const isCellEditable = this.isCellEditable(column, rowNode);
        const fieldValueOptions = this.getFieldValueOptions(column, rowNode);
        const fieldType = isCellEditable
            ? !!(fieldValueOptions === null || fieldValueOptions === void 0 ? void 0 : fieldValueOptions.length)
                ? 'select'
                : this.getFieldTypeFromColumnType(column)
            : 'textOutput';
        const defaultValue = rowNode
            ? isCellEditable
                ? this.getGridApi().getRawValueFromRowNode(rowNode, column.columnId)
                : this.getGridApi().getDisplayValueFromRowNode(rowNode, column.columnId)
            : null;
        return {
            label: this.getFormFieldLabel(type, column, rowNode),
            name: column.columnId,
            defaultValue,
            fieldType,
            options: fieldValueOptions,
        };
    }
    getFormFieldLabel(type, column, rowNode) {
        const customFieldLabel = typeof this.actionRowFormOptions.formFieldLabel === 'function'
            ? this.actionRowFormOptions.formFieldLabel(this.buildFormFieldLabelContext(type, column, rowNode))
            : undefined;
        return customFieldLabel !== null && customFieldLabel !== void 0 ? customFieldLabel : column.friendlyName;
    }
    buildFormFieldLabelContext(type, column, rowNode) {
        return Object.assign(Object.assign({ rowNode,
            column }, this.getAdaptableInternalApi().buildBaseContext()), { type: type });
    }
    getFieldTypeFromColumnType(column) {
        switch (column.dataType) {
            case 'Boolean':
                return 'checkbox';
            case 'Date':
                return 'date';
            case 'Number':
                return 'number';
            default:
                // everything else is a plain text input
                return 'text';
        }
    }
    getFieldValueOptions(column, rowNode) {
        const editLookUpItem = this.getAdaptableApi().userInterfaceApi.getEditLookUpItemForColumn(column);
        if (!editLookUpItem) {
            return;
        }
        const gridCell = rowNode
            ? this.getGridApi().getGridCellFromRowNode(rowNode, column.columnId)
            : undefined;
        const editLookUpValues = this.getGridApi().internalApi.getEditLookUpValuesForColumn(editLookUpItem, column, gridCell);
        return editLookUpValues === null || editLookUpValues === void 0 ? void 0 : editLookUpValues.map((value) => ({
            value,
            label: value,
        }));
    }
    getColDefsForActionRowColumns() {
        const actionButtons = this.getActionRowButtonDefs();
        if (!actionButtons.length) {
            return [];
        }
        return [
            {
                headerName: '',
                colId: GeneralConstants_1.ADAPTABLE_ROW_ACTION_BUTTONS,
                hide: false,
                editable: false,
                // 15px is the icon width + left&right padding + left&right border
                width: Math.max(actionButtons.length * (UIHelper_1.default.getSimpleButtonPaddingWidth() * 2 + 15) + 2, 
                // If the width of the column is to small, the width will not be applied
                // this triggers the setLayout an infinite loop because the width read from the grid is always different
                40),
                resizable: false,
                lockVisible: true,
                suppressColumnsToolPanel: true,
                suppressFiltersToolPanel: true,
                suppressHeaderMenuButton: true,
                suppressMovable: true,
                filter: false,
                sortable: false,
                enableRowGroup: false,
                pinned: this.getActionRowOptions().actionRowButtonOptions.position === 'pinnedRight'
                    ? 'right'
                    : 'left',
                cellRenderer: this.getAdaptableVariant() === 'react' ? ActionColumnRenderer_1.ReactActionColumnRenderer : ActionColumnRenderer_1.ActionColumnRenderer,
                cellClass: GeneralConstants_1.ADAPTABLE_ROW_ACTION_BUTTONS,
                type: [GeneralConstants_1.AB_SPECIAL_COLUMN, 'abColDefObject'],
            },
        ];
    }
    getActionRowButtonDefs() {
        const actionRowButtons = this.getActionRowApi().getActionRowButtons();
        if (!(actionRowButtons === null || actionRowButtons === void 0 ? void 0 : actionRowButtons.length)) {
            return [];
        }
        const defaultActionRowButtonConfiguration = {
            create: {
                icon: {
                    name: 'add',
                },
                tooltip: 'Create',
                onClick: () => {
                    this.getActionRowApi().displayCreateActionRow();
                },
            },
            edit: {
                icon: {
                    name: 'edit',
                },
                tooltip: 'Edit',
                onClick: (button, context) => {
                    this.getActionRowApi().displayEditActionRow(context.primaryKeyValue);
                },
            },
            clone: {
                icon: {
                    name: 'clone',
                },
                tooltip: 'Clone',
                onClick: (button, context) => {
                    this.getActionRowApi().displayCloneActionRow(context.primaryKeyValue);
                },
            },
            delete: {
                icon: {
                    name: 'delete',
                },
                tooltip: 'Delete',
                onClick: (button, context) => {
                    var _a, _b;
                    const eventInfo = Object.assign({ type: 'rowDeleted', rowNode: context.rowNode }, this.getAdaptableInternalApi().buildBaseContext());
                    this.getEventApi().emit('ActionRowSubmitted', eventInfo);
                    (_b = (_a = this.getActionRowOptions().actionRowFormOptions).onFormSubmit) === null || _b === void 0 ? void 0 : _b.call(_a, eventInfo);
                },
            },
        };
        const actionButtons = actionRowButtons
            .map((actionRowButtonType) => {
            var _a, _b;
            const defaultButtonConfig = defaultActionRowButtonConfiguration[actionRowButtonType];
            if (!defaultButtonConfig) {
                // should NOT happen unless the user sent some invalid button type in the predefined config
                return;
            }
            const customButtonConfig = (_b = (_a = this.getActionRowOptions().actionRowButtonOptions).customConfiguration) === null || _b === void 0 ? void 0 : _b.call(_a, Object.assign(Object.assign({}, this.getAdaptableInternalApi().buildBaseContext()), { actionRowButtonType }));
            if (!customButtonConfig) {
                return defaultButtonConfig;
            }
            return Object.assign(Object.assign({}, defaultButtonConfig), customButtonConfig);
        })
            .filter(Boolean);
        return actionButtons;
    }
}
exports.ActionRowInternalApi = ActionRowInternalApi;
