import { BooleanDataDefinition } from "../../../Common/Data/Definitions/BooleanDataDefinition";
import { ObjectDataDefinition } from "../../../Common/Data/Definitions/ObjectDataDefinition";
import { XDataDefinition } from "../../../Common/Data/XDataDefinition";
import { XDataType } from "../../../Common/Data/XDataType";
import { DataUtilities } from "../../../Common/DataUtilities";
import { Executable } from "../../../Common/Execution/Executable";
import { ValidationIssue } from "../../../Common/IDesignValidationProvider";
import { TableColumn } from "../Shared/TableColumn";
export class BaseRuleTableDefinition extends Executable {
    constructor() {
        super(...arguments);
        this._resultColumns = [];
        this._defaultResult = {};
        this._allowDefaultResults = true;
    }
    get allowDefaultResults() {
        return this._allowDefaultResults;
    }
    set allowDefaultResults(allowDefaultResults) {
        this._allowDefaultResults = allowDefaultResults;
    }
    set executionResult(res) {
        let executionResult;
        if (res instanceof Function) {
            executionResult = res();
        }
        else {
            executionResult = res;
        }
        // initialize
        this._resultColumns = [];
        this._defaultResult = {};
        if (!executionResult) {
            // no need this code?
            this.addResultColumn();
        }
        else {
            for (let field of executionResult.fields) {
                let rescol = this.addResultColumnInternal(field.name);
                rescol.dataType = field.type;
            }
            if (executionResult.fields.length === 0 && res instanceof XDataDefinition) {
                let rescol = this.addResultColumnInternal("result1");
                // update the output;
                res.fields.push(DataUtilities.createDataByType(rescol.dataType, rescol.name));
            }
        }
        this.syncDefaultResults();
        this.syncAllRows();
        this._executionResult = res;
    }
    get executionResult() {
        return this._executionResult;
    }
    getResultColumnByName(name) {
        return this.resultColumns.find((c) => c.name === name);
    }
    get defaultResult() {
        return this._defaultResult;
    }
    get resultColumns() {
        return this._resultColumns;
    }
    syncAllRows() {
        throw new Error("not implemented");
    }
    syncDefaultResults() {
        throw new Error("not implemented");
    }
    addResultColumnInternal(name) {
        const newresultcol = new TableColumn();
        if (!name) {
            let index = this.resultColumns.length + 1;
            name = "result_" + index;
            while (this.getResultColumnByName(name) !== undefined) {
                index = index + 1;
            }
            name = "result_" + index;
        }
        newresultcol.name = name;
        newresultcol.dataType = XDataType.STRING;
        this._resultColumns.push(newresultcol);
        return newresultcol;
    }
    addResultColumn(name) {
        if (!this.canChangeOutputs) {
            throw new Error("cannot add result columns because the outputs are specified by API");
        }
        let rescol = this.addResultColumnInternal(name);
        // update the output;
        this.getExecutionResult().fields.push(DataUtilities.createDataByType(rescol.dataType, rescol.name));
        this.syncDefaultResults();
        this.syncAllRows();
        return rescol;
    }
    removeResultColumn(id) {
        if (!this.canChangeOutputs) {
            throw new Error("cannot add result columns because the outputs are specified by API");
        }
        if (this._resultColumns.length > 1) {
            let resultColIdx = this._resultColumns.findIndex((resultCol) => resultCol._id === id);
            if (resultColIdx < 0)
                return;
            let resultcol = this._resultColumns[resultColIdx];
            this._resultColumns.splice(resultColIdx, 1);
            this.getExecutionResult().fields = this.getExecutionResult().fields.filter((f) => f.name !== resultcol.name || f.type !== resultcol.dataType);
            this.syncDefaultResults();
            this.syncAllRows();
        }
    }
    getDefaultResultByColumnId(columnId) {
        return this.defaultResult[columnId];
    }
    getResultColumnType(resultcol) {
        return this.getExecutionResult().fields.find((f) => f.name === resultcol.name && f.type === resultcol.dataType);
    }
    setResultColumnType(rule, dataType) {
        if (!this.canChangeOutputs)
            throw new Error("it's not editable");
        let defaultResult = this.getDefaultResultByColumnId(rule._id);
        // not sure if it's needed
        if (defaultResult) {
            if (dataType instanceof BooleanDataDefinition &&
                (defaultResult.value === undefined || defaultResult.value === null)) {
                defaultResult.value = false;
            }
            defaultResult.value = dataType.convert(defaultResult.value);
        }
        let outputdef = this.getExecutionResult();
        // remove old and add new;
        outputdef.fields = outputdef.fields.map((f) => {
            if (f.name === rule.name && f.type === rule.dataType) {
                return dataType;
            }
            return f;
        });
        rule.name = dataType.name;
        rule.dataType = dataType.type;
    }
    getResultColumnValidationIssues(rescol) {
        let issues = rescol.getDesignValidationIssues();
        if (!rescol.dataType) {
            issues.push(new ValidationIssue("datatype is not set"));
        }
        if (this.resultColumns.find((resC) => resC._id !== rescol._id && resC.name === rescol.name)) {
            issues.push(new ValidationIssue("duplicate names"));
        }
        let datadef = this.getResultColumnType(rescol);
        if (!datadef) {
            issues.push(new ValidationIssue("data path is incorrect"));
        }
        else if (datadef instanceof ObjectDataDefinition) {
            if (datadef.fields.length === 0) {
                issues.push(new ValidationIssue("fields are not configured"));
            }
        }
        return issues;
    }
    getResultCellValidationIssues(cell) {
        let issues = [];
        let resultcol = this.resultColumns.find((rescol) => rescol._id === cell._columnId);
        if (!resultcol)
            issues.push(new ValidationIssue("invalid column id"));
        else {
            issues.push(...cell.validateCellData(DataUtilities.createDataByType(resultcol.dataType, resultcol.name)));
        }
        return issues;
    }
    getDefaultResultCellValidationIssues(resultcell) {
        let resultcol = this.resultColumns.find((resc) => resc._id === resultcell._columnId);
        let issues = resultcell.validateCellData(DataUtilities.createDataByType(resultcol === null || resultcol === void 0 ? void 0 : resultcol.dataType, resultcol === null || resultcol === void 0 ? void 0 : resultcol.name));
        return issues;
    }
}
//# sourceMappingURL=BaseRuleTableDefinition.js.map