"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");
const OPERATOR_COLUMN = 1;
const OPERAND_COLUM = 2;
var TMP = {};
class TutorialProjection {
    constructor() {
        this.projectionType = "text";
        this.showBrackets = false;
    }
    setEditor(e) {
        this.editor = e;
    }
    getBox(exp) {
        LOGGER.log("TutorialProjection.getBox [" + exp + "]");
        if (exp === null || exp === undefined) {
            console.log("BOX OF NULL/UNDEFINED element [" + exp + "]");
            return null;
        }
        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) {
            LOGGER.log("Calling projection for CoreTestModel");
            return this.createModelBox4(exp);
        }
        else if (exp instanceof CoreTestAttribute_1.CoreTestAttribute) {
            return this.createAttributeBox(exp);
        }
        else if (exp instanceof CoreTestSumExpression_1.CoreTestSumExpression) {
            return this.createSumBox(exp);
        }
        else if (PiModel_1.isPiBinaryExpression(exp)) {
            return this.createBinaryBox(exp);
        }
        throw new Error("No box defined for this expression:" + exp.piId());
    }
    createModelBox(model) {
        return new editor_1.HorizontalListBox(model, "model", [
            new editor_1.LabelBox(model, "model-label", "CoreTestModel"),
            new editor_1.TextBox(model, "model-name", () => model.name, (c) => (model.name = c))
        ]);
    }
    createModelBox2(model) {
        return new editor_1.HorizontalListBox(model, "model", [
            new editor_1.LabelBox(model, "model-label", "Model", {
                style: styles_1.projectitStyles.keyword
            }),
            new editor_1.TextBox(model, "model-name", () => model.name, (c) => (model.name = c), {
                placeHolder: "<name>"
            })
        ]);
    }
    createModelBox3(model) {
        return new editor_1.VerticalListBox(model, "model", [
            new editor_1.HorizontalListBox(model, "model-info", [
                new editor_1.LabelBox(model, "model-keyword", "Model", {
                    style: styles_1.projectitStyles.keyword
                }),
                new editor_1.TextBox(model, "model-name", () => model.name, (c) => (model.name = c), {
                    placeHolder: "<name>"
                })
            ]),
            new editor_1.LabelBox(model, "entity-keyword", "Entities", {
                style: styles_1.projectitStyles.keyword
            }),
            new editor_1.VerticalListBox(model, "entity-list", model.units[0].entities.map(ent => {
                return this.createEntityBox(ent);
            }))
        ]);
    }
    createModelBox4(model) {
        LOGGER.log("createModelBox4 [" + model + "]");
        return new editor_1.VerticalListBox(model, "model", [
            new editor_1.HorizontalListBox(model, "model-info", [
                new editor_1.LabelBox(model, "model-keyword", "CoreTestModel", {
                    style: styles_1.projectitStyles.keyword
                }),
                new editor_1.TextBox(model, "model-name", () => model.name, (c) => (model.name = c), {
                    placeHolder: "<name>"
                })
            ]),
            new editor_1.LabelBox(model, "entity-list", "Entities", {
                style: styles_1.projectitStyles.keyword
            }),
            new editor_1.VerticalListBox(model, "entities", model.units[0].entities.map(ent => {
                return this.createEntityBox3(ent);
            })).addChild(new editor_1.AliasBox(model, "end-of-entity-list", "add entity", { style: styles_1.projectitStyles.indent })),
            new editor_1.LabelBox(model, "functions-list", "Functions", {
                style: styles_1.projectitStyles.keyword
            }),
            new editor_1.VerticalListBox(model, "functions", model.functions.map(fun => {
                return this.createFunctionBox(fun);
            }))
        ]);
    }
    createBinaryBox(exp) {
        if (this.projectionType === "tree") {
            return this.createBinaryBoxTree(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(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", [this.getBox(exp.piLeft()), this.getBox(exp.piRight())])
        ], {
            style: styles_1.projectitStyles.tree
        });
        return result;
    }
    createAttributeBox(att) {
        return new editor_1.HorizontalListBox(att, "attribute", [
            new editor_1.TextBox(att, "attribute-name", () => {
                return att.name;
            }, (v) => {
                att.name = v;
            }),
            new editor_1.LabelBox(att, "colon", ":"),
            new editor_1.TextBox(att, "attribute-type", () => {
                return att.type.asString();
            }, (v) => {
                att.type = testmodel_1.CoreTestAttributeType.fromString(v);
            })
        ], { style: styles_1.projectitStyles.indent });
    }
    createParameterBox(parameter) {
        return new editor_1.HorizontalListBox(parameter, "parameter", [
            new editor_1.TextBox(parameter, "parameter-name", () => {
                return parameter.name;
            }, (v) => {
                parameter.name = v;
            }),
            new editor_1.LabelBox(parameter, "colon", ":"),
            new editor_1.TextBox(parameter, "parameter-type", () => {
                return parameter.type.asString();
            }, (v) => {
            })
        ], { style: styles_1.projectitStyles.indent });
    }
    createEntityBox1(entity) {
        return new editor_1.VerticalListBox(entity, "entity", [
            new editor_1.HorizontalListBox(entity, "entity-keyword", [
                new editor_1.LabelBox(entity, "entity-label", "entity", {
                    style: styles_1.projectitStyles.keyword
                }),
                new editor_1.TextBox(entity, "entity-name", () => entity.name, (c) => (entity.name = c))
            ]),
            new editor_1.VerticalListBox(entity, "attributes", entity.attributes.map(att => {
                return this.createAttributeBox(att);
            }))
        ]);
    }
    createEntityBox(entity) {
        return new editor_1.VerticalListBox(entity, "entity", [
            new editor_1.HorizontalListBox(entity, "entity-info", [
                new editor_1.LabelBox(entity, "entity-keyword", "Entity", {
                    style: styles_1.projectitStyles.keyword
                }),
                new editor_1.TextBox(entity, "entity-name", () => entity.name, (c) => (entity.name = c), {
                    placeHolder: "<name>"
                })
            ]),
            new editor_1.VerticalListBox(entity, "attribute-list", entity.attributes.map(att => {
                return this.createAttributeBox(att);
            }))
        ], { style: styles_1.projectitStyles.indent });
    }
    createEntityBox3(entity) {
        return new editor_1.VerticalListBox(entity, "entity", [
            new editor_1.HorizontalListBox(entity, "entity-keyword", [
                new editor_1.LabelBox(entity, "entity-label", "entity", {
                    style: styles_1.projectitStyles.keyword
                }),
                new editor_1.TextBox(entity, "entity-name", () => entity.name, (c) => (entity.name = c))
            ]),
            new editor_1.VerticalListBox(entity, "attributes", entity.attributes.map(att => {
                return this.createAttributeBox(att);
            })).addChild(new editor_1.AliasBox(entity, "end-of-attribute-list", "add attribute", { style: styles_1.projectitStyles.indent }))
        ], {
            style: styles_1.projectitStyles.indent
        });
    }
    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;
    }
    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(exp);
    }
    createComparisonBox(exp) {
        LOGGER.info(this, "createComparisonBox: ");
        return this.createBinaryBox(exp);
    }
    createMultiplyBox(exp) {
        LOGGER.info(this, "createMultiplyBox: ");
        return this.createBinaryBox(exp);
    }
    createDivideBox(exp) {
        LOGGER.info(this, "createDivideBox: ");
        return this.createBinaryBox(exp);
    }
    createAndBox(exp) {
        LOGGER.info(this, "createAndBox: ");
        return this.createBinaryBox(exp);
    }
    createOrBox(exp) {
        LOGGER.info(this, "createOrBox: ");
        switch (this.projectionType) {
            case "text":
                return this.createBinaryBox(exp);
            case "orboxed":
                return this.createOrBoxGrid(exp);
            default:
                return this.createBinaryBox(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) {
        return new editor_1.VerticalListBox(fun, "function", [
            new editor_1.HorizontalListBox(fun, "fun-keyword", [
                new editor_1.LabelBox(fun, "fun-label", "function", {
                    style: styles_1.projectitStyles.keyword
                }),
                new editor_1.TextBox(fun, "fun-name", () => fun.name, (c) => (fun.name = c))
            ]),
            new editor_1.VerticalListBox(fun, "parameters", fun.parameters.map(att => {
                return this.createParameterBox(att);
            })).addChild(new editor_1.AliasBox(fun, "end-of-parameter-list", "add parameter", { style: styles_1.projectitStyles.indent }))
        ], {
            style: styles_1.projectitStyles.indent
        });
    }
    createFunctionBoxGrid(fun) {
        LOGGER.info(this, "createFunctionBox: ");
        let cells = [];
        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)
], TutorialProjection.prototype, "projectionType", void 0);
__decorate([
    mobx_1.observable,
    __metadata("design:type", Boolean)
], TutorialProjection.prototype, "showBrackets", void 0);
exports.TutorialProjection = TutorialProjection;
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;
    }
}
function createEntity(box, editor) {
    return new CoreTestEntity_1.CoreTestEntity();
}
exports.createEntity = createEntity;
//# sourceMappingURL=TutorialProjection.js.map