"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RowFormInternalApi = void 0;
const ApiBase_1 = require("../Implementation/ApiBase");
class RowFormInternalApi extends ApiBase_1.ApiBase {
    // Row Form Methods
    buildRowEditForm(rowNode) {
        return this.buildRowForm('rowEdited', rowNode);
    }
    buildRowCreateForm(clonedRowNode) {
        return this.buildRowForm('rowCreated', clonedRowNode);
    }
    buildRowForm(type, rowNode) {
        const formFields = this.buildRowFormFields(type, rowNode);
        const formButtons = this.buidRowFormButtons(type, rowNode, formFields);
        const formTitle = this.getFormTitle(type, rowNode);
        const formDescription = this.getFormDescription(type, rowNode);
        const rowForm = {
            title: formTitle,
            description: formDescription,
            fields: formFields,
            buttons: formButtons,
        };
        return rowForm;
    }
    getFormTitle(type, rowNode) {
        const rowFormOptions = this.getRowFormOptions();
        if (rowFormOptions.rowFormTitle == undefined) {
            return type === 'rowCreated' ? 'Create New Row' : 'Edit Row';
        }
        return typeof rowFormOptions.rowFormTitle === 'function'
            ? rowFormOptions.rowFormTitle(this.buildFormParamContext(type, rowNode))
            : rowFormOptions.rowFormTitle;
    }
    buildFormParamContext(type, rowNode) {
        return {
            rowNode,
            ...this.getAdaptableInternalApi().buildBaseContext(),
            type: type,
        };
    }
    getFormDescription(type, rowNode) {
        const rowFormOptions = this.getRowFormOptions();
        return typeof rowFormOptions.rowFormDescription === 'function'
            ? rowFormOptions.rowFormDescription(this.buildFormParamContext(type, rowNode))
            : rowFormOptions.rowFormDescription;
    }
    buidRowFormButtons(type, rowNode, formFields) {
        // 1. check if there are custom user provided buttons
        if (Array.isArray(this.getRowFormOptions().rowFormButtons)) {
            return this.getRowFormOptions().rowFormButtons;
        }
        // 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) => {
                // 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'
                    ? {
                        type: 'rowCreated',
                        formData: this.prepareCreateData(formFields, context),
                        ...this.getAdaptableInternalApi().buildBaseContext(),
                        clonedRowNode: rowNode,
                    }
                    : {
                        type: 'rowEdited',
                        formData: this.prepareEditData(formFields, context),
                        rowNode: rowNode,
                        ...this.getAdaptableInternalApi().buildBaseContext(),
                    };
                this.getEventApi().internalApi.fireRowFormSubmittedEvent(eventInfo);
                this.getRowFormOptions()?.onRowFormSubmit?.(eventInfo);
            },
        };
        return [cancelButton, saveButton];
    }
    prepareCreateData(formFields, context) {
        // when creating we just omit values that are not set
        const dataToSave = { ...context.formData };
        for (const formField of formFields) {
            if (dataToSave[formField.name] === '') {
                delete dataToSave[formField.name];
            }
        }
        return dataToSave;
    }
    prepareEditData(formFields, context) {
        const dataToSave = { ...context.formData };
        for (const formField of formFields) {
            if (formField.fieldType === 'textOutput') {
                delete dataToSave[formField.name];
            }
        }
        const pkValue = this.getGridApi().getPrimaryKeyValueForRowNode(context.rowNode);
        dataToSave[this.getOptions().primaryKey] = pkValue;
        return dataToSave;
    }
    buildRowFormFields(rowFormType, 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.showColumnInRowForm(column, rowFormType));
        return relevantColumns.map((column) => this.buildRowFormField(rowFormType, column, rowNode));
    }
    showColumnInRowForm(adaptableColumn, rowFormType) {
        const showColumnFn = this.getRowFormOptions()?.includeColumnInRowForm;
        if (typeof showColumnFn === 'function') {
            return showColumnFn({
                ...this.getAdaptableInternalApi().buildBaseContext(),
                adaptableColumn,
                rowFormType: rowFormType,
            });
        }
        return true;
    }
    isCellEditable(column, rowNode) {
        if (!rowNode) {
            return !column.readOnly;
        }
        const gridCell = this.getGridApi().getGridCellFromRowNode(rowNode, column.columnId);
        return this.getGridApi().isCellEditable(gridCell);
    }
    buildRowFormField(type, column, rowNode) {
        const isCellEditable = this.isCellEditable(column, rowNode);
        const fieldValueOptions = this.getFieldValueOptions(column, rowNode);
        const fieldType = isCellEditable
            ? !!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.getRowFormFieldLabel(type, column, rowNode),
            name: column.columnId,
            defaultValue,
            fieldType,
            options: fieldValueOptions,
        };
    }
    getRowFormFieldLabel(type, column, rowNode) {
        const customFieldLabel = typeof this.getRowFormOptions().rowFormFieldLabel === 'function'
            ? this.getRowFormOptions().rowFormFieldLabel(this.buildFormFieldLabelContext(type, column, rowNode))
            : undefined;
        return customFieldLabel ?? column.friendlyName;
    }
    buildFormFieldLabelContext(type, column, rowNode) {
        return {
            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 shouldShowSelectCellEditor = this.getUserInterfaceApi().internalApi.shouldShowSelectCellEditor(column);
        if (!shouldShowSelectCellEditor) {
            return;
        }
        const returnValues = this.getGridApi().internalApi.getDistinctDisplayValuesForColumnOld(column.columnId);
        // FIXME add support for asynchronous custom select cell editor values
        // it involves refactoring the AdaptableForm & adaptableFormComponent
        // await this.getSelectCellEditorValuesForColumn(
        //   column,
        //   gridCell
        // );
        return returnValues?.map((value) => ({
            value,
            label: value,
        }));
    }
}
exports.RowFormInternalApi = RowFormInternalApi;
