import { __decorate, __metadata } from "tslib";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { BaseLogicExpression } from "./BaseLogic";
import { ExpressionValue } from "../../ExpressionValue";
import React from "react";
import styled from "styled-components";
import { ExpressionValueRenderer } from "../../ExpressionValueRenderer";
import { ExpressionLineDiv, ExpressionPiece } from "../../ExpressionStyles";
import { IconButton } from "@material-ui/core";
import { AutoBind } from "../../../Common/AutoBind";
import { InlineOptionSelect } from "../../../CommonUI/InlineOptionSelect";
import { PlusIcon } from "../../../CommonUI/Icon/PlusIcon";
import { DeleteIcon } from "../../../CommonUI/Icon/DeleteIcon";
import { ObserveState } from "../../../CommonUI/StateManagement/ObserveState";
import { StateManager } from "../../../CommonUI/StateManagement/StateManager";
import { ExpressionContext, ExpressionRenderType } from "../../ExpressionContext";
import { BooleanDataDefinition } from "../../../Common/Data/Definitions/BooleanDataDefinition";
import { ExpressionTestResultColorContext } from "../../Test/ExpressionTestResultColorContext";
import { TestContext } from "../../../Tester/TestContext";
const StyledBracketedDiv = styled.div `
    position: relative;
    display: flex;
    align-items: center;

    flex-direction: ${(props) => props.direction || "row"};

    ${(props) => props.renderType === ExpressionRenderType.FULL
    ? `
                padding: 2px 4px;
                margin-left: 6px;
                margin-right: 10px;

                ${props.hasChild
        ? `
                            flex: 1;
                        `
        : ``}

                &::before {
                    content: "";
                    width: 4px;
                    position: absolute;
                    top: 0;
                    left: 0;
                    bottom: 0;
                    border: 1px solid ${props.color || "#93a9bf"};
                    border-right: none;
                    border-top-left-radius: 3px;
                    border-bottom-left-radius: 3px;
                }

                &::after {
                    content: "";
                    width: 4px;
                    position: absolute;
                    top: 0;
                    right: 0;
                    bottom: 0;
                    border: 1px solid ${props.color || "#93a9bf"};
                    border-left: none;
                    border-top-right-radius: 3px;
                    border-bottom-right-radius: 3px;
                }

            `
    : `
                padding: 0;
            `}
`;
export const GroupedBracketedDiv = (props) => {
    var _a;
    const context = React.useContext(ExpressionContext);
    const testcolor = React.useContext(ExpressionTestResultColorContext);
    return (_jsx(StyledBracketedDiv, Object.assign({}, props, { renderType: context.renderType, compactColor: context.color, issueType: (_a = props.issue) === null || _a === void 0 ? void 0 : _a.level, color: testcolor }), void 0));
};
export var GroupingType;
(function (GroupingType) {
    GroupingType["AND"] = "and";
    GroupingType["OR"] = "or";
})(GroupingType || (GroupingType = {}));
export class AndGroup extends BaseLogicExpression {
    constructor() {
        super();
        this.__type = "And Group";
        this.typeOfGroup = GroupingType.AND;
        this.elements = [];
        this.expressionValueType = new BooleanDataDefinition();
        this.add();
    }
    getExpressionValues() {
        return this.elements;
    }
    getAllVariables() {
        let output = [];
        for (let f of this.getExpressionValues()) {
            output.push(...f.getAllVariables());
        }
        return output;
    }
    add() {
        let e = new ExpressionValue();
        if (this.editContext) {
            e.setEditContext(this.editContext, this);
            this.editContext.refresh();
        }
        e.expectedType = new BooleanDataDefinition();
        this.elements.push(e);
        StateManager.changed(this);
    }
    delete(index) {
        this.elements.splice(index, 1);
        if (this.editContext) {
            this.editContext.refresh();
        }
        StateManager.changed(this);
    }
    setEditContext(editContext, owner) {
        super.setEditContext(editContext, owner);
        for (let p of this.elements) {
            p.setEditContext(editContext, this);
        }
    }
    getTestValueColor(el, testcontext) {
        if (!testcontext)
            return undefined;
        if (!testcontext)
            return undefined;
        let testitem = testcontext.findItem(el._id);
        if ((testitem === null || testitem === void 0 ? void 0 : testitem.result) === "true") {
            return "#35B687";
        }
        else if ((testitem === null || testitem === void 0 ? void 0 : testitem.result) === "false")
            return "#EE3E54";
        return undefined;
    }
    render() {
        return (_jsx(ObserveState, { listenTo: this, control: () => (_jsx(GroupedBracketedDiv, Object.assign({ issue: this.getValidationIssues()[0], direction: "column" }, { children: this.elements.map((g, i) => {
                    return (_jsx(TestContext.Consumer, { children: (testcontext) => (_jsx(ExpressionTestResultColorContext.Provider, Object.assign({ value: this.getTestValueColor(g, testcontext) }, { children: _jsxs(ExpressionLineDiv, { children: [_jsx(ExpressionValueRenderer, { el: g }, "g-" + i), this.renderEndOfLine(i)] }, i) }), void 0)) }, g._id));
                }) }), void 0)) }, void 0));
    }
    renderEndOfLine(i) {
        return (_jsx(TestContext.Consumer, { children: (testcontext) => {
                if (testcontext)
                    return null;
                let isLast = i + 1 === this.elements.length;
                let isFirst = i === 0;
                if (isFirst && isLast) {
                    return (_jsx(ExpressionPiece, Object.assign({ "data-testid": "ExpressionGroup-add" }, { children: _jsx(IconButton, Object.assign({ size: "small", onClick: this.addToFromAction }, { children: _jsx(PlusIcon, {}, void 0) }), void 0) }), void 0));
                }
                else if (isFirst && !isLast) {
                    return (_jsx(ExpressionPiece, Object.assign({ "data-testid": "ExpressionGroup-add" }, { children: _jsx(ExpressionContext.Consumer, { children: (context) => (_jsx(InlineOptionSelect, { text: this.typeOfGroup, options: [GroupingType.AND, GroupingType.OR], onEdit: this.onGroupTypeSelect, readOnly: context.renderType === ExpressionRenderType.COMPACT ||
                                    context.renderType === ExpressionRenderType.TEXT }, void 0)) }, void 0) }), void 0));
                }
                else if (!isLast) {
                    return (_jsxs(ExpressionPiece, Object.assign({ "data-testid": "ExpressionGroup-add" }, { children: [_jsx(ExpressionContext.Consumer, { children: (context) => (_jsx(InlineOptionSelect, { text: this.typeOfGroup, options: [GroupingType.AND, GroupingType.OR], onEdit: this.onGroupTypeSelect, readOnly: context.renderType === ExpressionRenderType.COMPACT ||
                                        context.renderType === ExpressionRenderType.TEXT }, void 0)) }, void 0),
                            _jsx(IconButton, Object.assign({ size: "small", "aria-label": "delete", onClick: (event) => {
                                    event.stopPropagation();
                                    this.deleteToFromAction(i);
                                } }, { children: _jsx(DeleteIcon, {}, void 0) }), void 0)] }), void 0));
                }
                else if (isLast) {
                    return (_jsxs(ExpressionPiece, { children: [_jsx(IconButton, Object.assign({ size: "small", onClick: this.addToFromAction }, { children: _jsx(PlusIcon, {}, void 0) }), void 0),
                            _jsx(IconButton, Object.assign({ size: "small", "aria-label": "delete", onClick: (event) => {
                                    event.stopPropagation();
                                    this.deleteToFromAction(i);
                                } }, { children: _jsx(DeleteIcon, {}, void 0) }), void 0)] }, void 0));
                }
            } }, void 0));
    }
    addToFromAction(event) {
        event.stopPropagation();
        this.add();
    }
    deleteToFromAction(index) {
        this.delete(index);
    }
    onGroupTypeSelect(newGroup) {
        this.typeOfGroup = newGroup;
        StateManager.changed(this);
    }
    evaluate(data, testContext) {
        return !this.elements.find((e) => e.evaluate(data, testContext) === false);
    }
    getStorageData() {
        let data = super.getStorageData();
        Reflect.set(data, "typeOfGroup", this.typeOfGroup);
        let elementData = [];
        for (let e of this.elements) {
            elementData.push(e.getStorageData());
        }
        Reflect.set(data, "elements", elementData);
        return data;
    }
    setStorageData(data) {
        super.setStorageData(data);
        if (data === undefined)
            throw new Error("no data");
        this.typeOfGroup = Reflect.get(data, "typeOfGroup");
        let elementData = Reflect.get(data, "elements");
        // reset elements to empty.
        this.elements = [];
        for (let e of elementData) {
            let exp = new ExpressionValue();
            exp.setStorageData(e);
            if (exp) {
                this.elements.push(exp);
            }
        }
    }
}
__decorate([
    AutoBind,
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", void 0)
], AndGroup.prototype, "addToFromAction", null);
__decorate([
    AutoBind,
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Number]),
    __metadata("design:returntype", void 0)
], AndGroup.prototype, "deleteToFromAction", null);
__decorate([
    AutoBind,
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", void 0)
], AndGroup.prototype, "onGroupTypeSelect", null);
export class OrGroup extends AndGroup {
    constructor() {
        super();
        this.__type = "Or Group";
        this.typeOfGroup = GroupingType.OR;
    }
    evaluate(data, testContext) {
        return !!this.elements.find((e) => e.evaluate(data, testContext) === true);
    }
}
//# sourceMappingURL=Grouping.js.map