"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
const mobx_1 = require("mobx");
const PiModel_1 = require("../../language/PiModel");
const editor_1 = require("../../editor");
const util_1 = require("../../util");
const Styles_1 = require("../../editor/components/styles/Styles");
const Icons_1 = require("./Icons");
const CoreTestSumExpression_1 = require("../testmodel/expressions/CoreTestSumExpression");
const CoreTestUtil_1 = require("../testmodel/expressions/CoreTestUtil");
const styles_1 = require("../styles/styles");
require("flatted");
const CoreTestModel_1 = require("../testmodel/CoreTestModel");
const CoreTestAttribute_1 = require("../testmodel/domain/CoreTestAttribute");
const CoreTestEntity_1 = require("../testmodel/domain/CoreTestEntity");
const CoreTestFunction_1 = require("../testmodel/domain/CoreTestFunction");
const testmodel_1 = require("../testmodel");
const LOGGER = new util_1.PiLogger("CoreTestProjection").mute();
const OPERATOR_COLUMN = 1;
const OPERAND_COLUM = 2;
var TMP = {};
class CoreTestProjection {
    constructor() {
        this.name = "";
        this.projectionType = "text";
        this.showBrackets = false;
    }
    setEditor(e) {
        this.editor = e;
    }
    getBox(exp) {
        if (exp instanceof testmodel_1.CoreTestStringLiteralExpression) {
            return this.createStringLiteralBox(exp);
        }
        else if (exp instanceof testmodel_1.CoreTestNumberLiteralExpression) {
            return this.createNumberLiteralBox(exp);
        }
        else if (exp instanceof testmodel_1.CoreTestPlusExpression) {
            return this.createPlusBox(exp);
        }
        else if (exp instanceof testmodel_1.CoreTestMultiplyExpression) {
            return this.createMultiplyBox(exp);
        }
        else if (exp instanceof testmodel_1.CoreTestAndExpression) {
            return this.createAndBox(exp);
        }
        else if (exp instanceof testmodel_1.CoreTestOrExpression) {
            return this.createOrBox(exp);
        }
        else if (exp instanceof testmodel_1.CoreTestDivideExpression) {
            return this.createDivideBox(exp);
        }
        else if (exp instanceof testmodel_1.CoretestComparisonExpression) {
            return this.createComparisonBox(exp);
        }
        else if (exp instanceof CoreTestFunction_1.CoreTestFunction) {
            return this.createFunctionBox(exp);
        }
        else if (exp instanceof CoreTestEntity_1.CoreTestEntity) {
            return this.createEntityBox(exp);
        }
        else if (exp instanceof CoreTestModel_1.CoreTestModel) {
            return this.createModelBox(exp);
        }
        else if (exp instanceof CoreTestEntity_1.CoreTestEntity) {
            return this.createEntityBox(exp);
        }
        else if (exp instanceof CoreTestSumExpression_1.CoreTestSumExpression) {
            return this.createSumBox(exp);
        }
        else if (PiModel_1.isPiBinaryExpression(exp)) {
            return this.createBinaryBox(this, exp);
        }
        throw new Error("No box defined for this expression:" + exp.piId());
    }
    createBinaryBox(projection, exp) {
        if (this.projectionType === "tree") {
            return this.createBinaryBoxTree(projection, exp);
        }
        else {
            let binBox = util_1.createDefaultBinaryBox(this, exp, CoreTestUtil_1.symbol(exp), this.editor);
            if (this.showBrackets &&
                !!exp.piContainer().container &&
                PiModel_1.isPiBinaryExpression(exp.piContainer().container)) {
                return new editor_1.HorizontalListBox(exp, "brackets", [
                    new editor_1.LabelBox(exp, "open-bracket", "("),
                    binBox,
                    new editor_1.LabelBox(exp, "close-bracket", ")")
                ]);
            }
            else {
                return binBox;
            }
        }
    }
    createBinaryBoxTree(projection, exp) {
        let result = new editor_1.HorizontalListBox(exp, "binary1", [
            new editor_1.LabelBox(exp, "symbol", CoreTestUtil_1.symbol(exp)),
            new editor_1.VerticalListBox(exp, "args", [projection.getBox(exp.piLeft()), projection.getBox(exp.piRight())])
        ], {
            style: styles_1.projectitStyles.tree
        });
        return result;
    }
    createEntityBox(entity) {
        LOGGER.info(this, "createEntityBox: ");
        let cells = [];
        cells.push({
            row: 1,
            column: 1,
            box: new editor_1.TextBox(entity, "entity-name", () => entity.name, (s) => (entity.name = s), {
                deleteWhenEmpty: true,
                placeHolder: "<enter entity name>",
                keyPressAction: (currentText, key, index) => {
                    return isName(currentText, key, index);
                }
            })
        });
        cells.push({
            row: 2,
            column: 1,
            box: this.createAttributeGrid(entity)
        });
        return new editor_1.GridBox(entity, "entity-all", cells);
    }
    createEntityBoxGrid(entity) {
        LOGGER.info(this, "createEntityBox: ");
        let cells = [
            {
                row: 1,
                column: 1,
                columnSpan: 2,
                box: new editor_1.TextBox(entity, "entity-name", () => entity.name, (v) => (entity.name = v))
            }
        ];
        let row = 2;
        entity.attributes.forEach(a => {
            cells.push({
                row: row,
                column: 1,
                box: new editor_1.TextBox(a, "attr-name-" + row, () => a.name, (v) => (a.name = v))
            });
            cells.push({
                row: row,
                column: 2,
                box: new editor_1.TextBox(a, "attr-type-" + row, () => a.type.asString(), (v) => { })
            });
            row++;
        });
        return new editor_1.GridBox(entity, "entity", cells);
    }
    createAttributeGrid(entity) {
        return util_1.GridUtil.createCollectionRowGrid(entity, "attr-grid", "attributes", entity.attributes, ["name", "type"], [
            (att) => {
                return new editor_1.TextBox(att, "attr-name", () => att.name, (s) => (att.name = s), {
                    deleteWhenEmpty: true,
                    keyPressAction: (currentText, key, index) => {
                        return isName(currentText, key, index);
                    },
                    placeHolder: "<name>"
                });
            },
            (attr) => {
                return new editor_1.TextBox(attr, "attr-type", () => attr.type.asString(), (v) => { });
            }
        ], (box, editor) => {
            return new CoreTestAttribute_1.CoreTestAttribute();
        }, this.editor);
    }
    createSumBox(sum) {
        let cells = [
            {
                row: 3,
                column: 1,
                columnSpan: 2,
                box: this.getBox(sum.from),
                style: styles_1.projectitStyles.mycell
            },
            {
                row: 2,
                column: 1,
                box: new editor_1.SvgBox(sum, "sum-icon", Icons_1.sumIcon, {
                    width: 50,
                    height: 50,
                    selectable: false
                }),
                style: styles_1.projectitStyles.mycell
            },
            {
                row: 1,
                column: 1,
                columnSpan: 2,
                box: this.getBox(sum.to),
                style: styles_1.projectitStyles.mycell
            },
            {
                row: 2,
                column: 2,
                box: new editor_1.HorizontalListBox(sum, "sum-body", [
                    new editor_1.LabelBox(sum, "sum-body-open", "(", { style: Styles_1.STYLES.bracket }),
                    this.getBox(sum.body),
                    new editor_1.LabelBox(sum, "sum-body-close", ")", { style: Styles_1.STYLES.bracket })
                ]),
                style: styles_1.projectitStyles.mycell
            }
        ];
        let result = new editor_1.GridBox(sum, "sum-all", cells, {
            style: styles_1.projectitStyles.mygrid
        });
        return util_1.createDefaultExpressionBox(sum, "sum-exp", [result]);
    }
    textbox(element, property) {
        let result = null;
        const value = element[property];
        if (value !== undefined && value != null && typeof value === "string") {
            result = new editor_1.TextBox(element, "property", () => element[property], (v) => (element[property] = v));
        }
        else {
            util_1.PiUtils.CHECK(false, "Property " + property + " does not exist or is not a string");
        }
        return result;
    }
    createModelBox(model) {
        LOGGER.info(this, "createModelBox");
        return new editor_1.VerticalListBox(model, "model", [
            new editor_1.HorizontalListBox(model, "model-keyword", [
                new editor_1.LabelBox(model, "model-label", "model", {
                    style: styles_1.projectitStyles.keyword
                }),
                new editor_1.TextBox(model, "textC", () => model.name, (c) => (model.name = c))
            ]),
            new editor_1.LabelBox(model, "entityexpression", "expression", {
                style: styles_1.projectitStyles.keyword
            }),
            this.getBox(model.functions[0].expression)
        ]);
    }
    createStringLiteralBox(literal) {
        LOGGER.info(this, "createStringLiteralBox: " + literal.value);
        return util_1.createDefaultExpressionBox(literal, "string-literal-exp", [
            new editor_1.HorizontalListBox(literal, "string-literal", [
                new editor_1.LabelBox(literal, "start-quote", '"', { selectable: false }),
                new editor_1.TextBox(literal, "string-value", () => literal.value, (v) => (literal.value = v), {
                    style: styles_1.projectitStyles.stringLiteral,
                    deleteWhenEmptyAndErase: true
                }),
                new editor_1.LabelBox(literal, "end-quote", '"', { selectable: false })
            ])
        ]);
    }
    createStringLiteralBox1(literal) {
        return util_1.createDefaultExpressionBox(literal, "string-literal-exp", [
            new editor_1.HorizontalListBox(literal, "string-literal", [
                new editor_1.LabelBox(literal, "start-quote", '"'),
                new editor_1.TextBox(literal, "string-value", () => literal.value, (v) => (literal.value = v)),
                new editor_1.LabelBox(literal, "end-quote", '"')
            ])
        ]);
    }
    createStringLiteralBoxSimple(literal) {
        return util_1.createDefaultExpressionBox(literal, "string-literal-exp", [
            new editor_1.HorizontalListBox(literal, "string-literal", [
                new editor_1.LabelBox(literal, "start-quote", '"'),
                new editor_1.TextBox(literal, "string-value", () => literal.value, (v) => (literal.value = v)),
                new editor_1.LabelBox(literal, "end-quote", '"')
            ])
        ]);
    }
    createPlusBox(exp) {
        LOGGER.info(this, "createPlusBox: ");
        return this.createBinaryBox(this, exp);
    }
    createComparisonBox(exp) {
        LOGGER.info(this, "createComparisonBox: ");
        return this.createBinaryBox(this, exp);
    }
    createMultiplyBox(exp) {
        LOGGER.info(this, "createMultiplyBox: ");
        return this.createBinaryBox(this, exp);
    }
    createDivideBox(exp) {
        LOGGER.info(this, "createDivideBox: ");
        return this.createBinaryBox(this, exp);
    }
    createAndBox(exp) {
        LOGGER.info(this, "createAndBox: ");
        return this.createBinaryBox(this, exp);
    }
    createOrBox(exp) {
        LOGGER.info(this, "createOrBox: ");
        switch (this.projectionType) {
            case "text":
                return this.createBinaryBox(this, exp);
            case "orboxed":
                return this.createOrBoxGrid(exp);
            default:
                return this.createBinaryBox(this, exp);
        }
    }
    createNumberLiteralBox(exp) {
        LOGGER.info(this, "createNumberLiteralBox: ");
        return util_1.createDefaultExpressionBox(exp, "number-literal", [
            new editor_1.TextBox(exp, "num-literal-value", () => exp.value, (v) => (exp.value = v), {
                deleteWhenEmpty: true,
                style: styles_1.projectitStyles.stringLiteral,
                keyPressAction: (currentText, key, index) => {
                    return isNumber(currentText, key, index);
                }
            })
        ]);
    }
    createFunctionBox(fun) {
        LOGGER.info(this, "createFunctionBox: ");
        let cells = [
            {
                row: 1,
                column: 1,
                box: new editor_1.LabelBox(fun, "fun-keyword", "function")
            },
            {
                row: 1,
                column: 2,
                box: new editor_1.TextBox(fun, "fun-name", () => fun.name, (v) => (fun.name = v))
            },
            {
                row: 1,
                column: 3,
                box: new editor_1.TextBox(fun, "fun-par1", () => fun.parameters[0].name, (v) => (fun.parameters[0].name = v))
            },
            {
                row: 2,
                column: 2,
                box: this.getBox(fun.expression)
            }
        ];
        let result = new editor_1.GridBox(fun, "function", cells);
        return result;
    }
    createOrBoxGrid(exp) {
        const gridCells = [];
        [
            {
                row: 1,
                column: 2,
                box: new editor_1.LabelBox(exp, "or-Box", () => "OR"),
                style: Styles_1.STYLES.gridcellOr,
                rowSpan: 2
            }
        ];
        if (exp.left instanceof testmodel_1.CoreTestOrExpression) {
            gridCells.push({
                row: 1,
                column: OPERATOR_COLUMN,
                box: new editor_1.LabelBox(exp, "or-Box", () => "or"),
                style: Styles_1.STYLES.gridcellOr,
                rowSpan: 3
            }, {
                row: 1,
                column: OPERAND_COLUM,
                box: this.getBox(exp.left.left),
                style: Styles_1.STYLES.gridcellFirst
            }, {
                row: 2,
                column: OPERAND_COLUM,
                box: this.getBox(exp.left.right),
                style: Styles_1.STYLES.gridcell
            }, {
                row: 3,
                column: OPERAND_COLUM,
                box: this.getBox(exp.right),
                style: Styles_1.STYLES.gridcellLast
            });
        }
        else {
            gridCells.push({
                row: 1,
                column: OPERATOR_COLUMN,
                box: new editor_1.LabelBox(exp, "or-Box", () => "or"),
                style: Styles_1.STYLES.gridcellOr,
                rowSpan: 2
            }, {
                row: 1,
                column: OPERAND_COLUM,
                box: this.getBox(exp.left),
                style: Styles_1.STYLES.gridcellFirst
            }, {
                row: 2,
                column: OPERAND_COLUM,
                box: this.getBox(exp.right),
                style: Styles_1.STYLES.gridcellLast
            });
        }
        return new editor_1.GridBox(exp, "grid-or", gridCells, { style: Styles_1.STYLES.grid });
    }
}
__decorate([
    mobx_1.observable,
    __metadata("design:type", String)
], CoreTestProjection.prototype, "projectionType", void 0);
__decorate([
    mobx_1.observable,
    __metadata("design:type", Boolean)
], CoreTestProjection.prototype, "showBrackets", void 0);
exports.CoreTestProjection = CoreTestProjection;
function isNumber(currentText, key, index) {
    if (isNaN(Number(key))) {
        if (index === currentText.length) {
            return editor_1.KeyPressAction.GOTO_NEXT;
        }
        else {
            return editor_1.KeyPressAction.NOT_OK;
        }
    }
    else {
        return editor_1.KeyPressAction.OK;
    }
}
function isName(currentText, key, index) {
    LOGGER.log("IsName key[" + key + "]");
    if (key === "Enter") {
        if (index === currentText.length) {
            return editor_1.KeyPressAction.GOTO_NEXT;
        }
        else {
            return editor_1.KeyPressAction.NOT_OK;
        }
    }
    else {
        return editor_1.KeyPressAction.OK;
    }
}
//# sourceMappingURL=CoreTestProjection.js.map