import * as Blockly from 'blockly';
import CategoryColors from './define_color'
import goog from './BlocklyFunction';


Blockly.Blocks.procedures_defnoreturn = {
    init: function () {
        var a = new Blockly.FieldTextInput(Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE, Blockly.Procedures.rename);
        a.setSpellcheck(!1);
        this.setInputsInline(!0);
        this.appendDummyInput().appendField(Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE).appendField(a, "NAME").appendField("", "PARAMS");
        this.setMutator(new Blockly.icons.MutatorIcon(["procedures_mutatorarg"],this));
        (this.workspace.options.comments || this.workspace.options.parentWorkspace && this.workspace.options.parentWorkspace.options.comments) && Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT && this.setCommentText(Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT);
        this.setColour(CategoryColors['Procedures']);
        this.setTooltip(Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP);
        this.setHelpUrl(Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL);
        this.arguments_ = [];
        this.setStatements_(!0);
        this.statementConnection_ = null
    },
    setStatements_: function (a) {
        this.hasStatements_ !== a && (a ? (this.appendStatementInput("STACK").appendField(Blockly.Msg.PROCEDURES_DEFNORETURN_DO),
            this.getInput("RETURN") && this.moveInputBefore("STACK", "RETURN")) : this.removeInput("STACK", !0),
            this.hasStatements_ = a)
    },
    updateParams_: function () {
        for (var a = !1, b = {}, c = 0; c < this.arguments_.length; c++) {
            if (b["arg_" + this.arguments_[c].toLowerCase()]) {
                a = !0;
                break
            }
            b["arg_" + this.arguments_[c].toLowerCase()] = !0
        }
        a ? this.setWarningText(Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING) : this.setWarningText(null);
        a = "";
        this.arguments_.length && (a = Blockly.Msg.PROCEDURES_BEFORE_PARAMS + " " + this.arguments_.join(", "));
        Blockly.Events.disable();
        try {
            this.setFieldValue(a, "PARAMS")
        } finally {
            Blockly.Events.enable()
        }
    },
    mutationToDom: function (a) {
        var b = document.createElement("mutation");
        a && b.setAttribute("name", this.getFieldValue("NAME"));
        for (var c = 0; c < this.arguments_.length; c++) {
            var e = document.createElement("arg");
            e.setAttribute("name", this.arguments_[c]);
            a && this.paramIds_ && e.setAttribute("paramId", this.paramIds_[c]);
            b.appendChild(e)
        }
        this.hasStatements_ || b.setAttribute("statements", "false");
        return b
    },
    domToMutation: function (a) {
        this.arguments_ = [];
        for (var b = 0, c; c = a.childNodes[b]; b++)
            "arg" == c.nodeName.toLowerCase() && this.arguments_.push(c.getAttribute("name"));
        this.updateParams_();
        Blockly.Procedures.mutateCallers(this);
        this.setStatements_("false" !== a.getAttribute("statements"))
    },
    decompose: function (a) {
        var b = a.newBlock("procedures_mutatorcontainer");
        b.initSvg();
        this.getInput("RETURN") ? b.setFieldValue(this.hasStatements_ ? "TRUE" : "FALSE", "STATEMENTS") : b.getInput("STATEMENT_INPUT").setVisible(!1);
        for (var c = b.getInput("STACK").connection, e = 0; e < this.arguments_.length; e++) {
            var d = a.newBlock("procedures_mutatorarg");
            d.initSvg();
            d.setFieldValue(this.arguments_[e], "NAME");
            d.oldLocation = e;
            c.connect(d.previousConnection);
            c = d.nextConnection
        }
        Blockly.Procedures.mutateCallers(this);
        return b
    },
    compose: function (a) {
        this.arguments_ = [];
        this.paramIds_ = [];
        for (var b = a.getInputTargetBlock("STACK"); b;)
            this.arguments_.push(b.getFieldValue("NAME")),
                this.paramIds_.push(b.id),
                b = b.nextConnection && b.nextConnection.targetBlock();
        this.updateParams_();
        Blockly.Procedures.mutateCallers(this);
        a = a.getFieldValue("STATEMENTS");
        if (null !== a && (a = "TRUE" == a,
            this.hasStatements_ != a))
            if (a)
                this.setStatements_(!0),
                    Blockly.icons.MutatorIcon.reconnect(this.statementConnection_, this, "STACK"),
                    this.statementConnection_ = null;
            else {
                a = this.getInput("STACK").connection;
                if (this.statementConnection_ = a.targetConnection)
                    a = a.targetBlock(),
                        a.unplug(),
                        a.bumpNeighbours_();
                this.setStatements_(!1)
            }
    },
    getProcedureDef: function () {
        return [this.getFieldValue("NAME"), this.arguments_, !1]
    },
    getVars: function () {
        return this.arguments_
    },
    renameVar: function (a, b) {
        for (var c = !1, e = 0; e < this.arguments_.length; e++)
            Blockly.Names.equals(a, this.arguments_[e]) && (this.arguments_[e] = b,
                c = !0);
        if (c && (this.updateParams_(),
            this.mutator.isVisible())) {
            c = this.mutator.workspace_.getAllBlocks();
            e = 0;
            for (var d; d = c[e]; e++)
                "procedures_mutatorarg" == d.type && Blockly.Names.equals(a, d.getFieldValue("NAME")) && d.setFieldValue(b, "NAME")
        }
    },
    customContextMenu: function (a) {
        var b = {
            enabled: !0
        }
            , c = this.getFieldValue("NAME");
        b.text = Blockly.Msg.PROCEDURES_CREATE_DO.replace("%1", c);
        var e = Blockly.dom.createDom("mutation");
        e.setAttribute("name", c);
        for (var d = 0; d < this.arguments_.length; d++)
            c = Blockly.dom.createDom("arg"),
                c.setAttribute("name", this.arguments_[d]),
                e.appendChild(c);
        e = Blockly.dom.createDom("block", null, e);
        e.setAttribute("type", this.callType_);
        b.callback = Blockly.ContextMenu.callbackFactory(this, e);
        a.push(b);
        if (!this.isCollapsed())
            for (d = 0; d < this.arguments_.length; d++)
                b = {
                    enabled: !0
                },
                    c = this.arguments_[d],
                    b.text = Blockly.Msg.VARIABLES_SET_CREATE_GET.replace("%1", c),
                    e = Blockly.dom.createDom("field", null, c),
                    e.setAttribute("name", "VAR"),
                    e = Blockly.dom.createDom("block", null, e),
                    e.setAttribute("type", "variables_get"),
                    b.callback = Blockly.ContextMenu.callbackFactory(this, e),
                    a.push(b)
    },
    callType_: "procedures_callnoreturn"
};
Blockly.Blocks.procedures_defreturn = {
    init: function () {
        var a = new Blockly.FieldTextInput(Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE, Blockly.Procedures.rename);
        a.setSpellcheck(!1);
        this.setInputsInline(!0);
        this.appendDummyInput().appendField(Blockly.Msg.PROCEDURES_DEFRETURN_TITLE).appendField(a, "NAME").appendField("", "PARAMS");
        this.appendValueInput("RETURN").setAlign(Blockly.ALIGN_RIGHT).appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);
        this.setMutator(new Blockly.icons.MutatorIcon(["procedures_mutatorarg"],this));
        (this.workspace.options.comments || this.workspace.options.parentWorkspace && this.workspace.options.parentWorkspace.options.comments) && Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT && this.setCommentText(Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT);
        this.setColour(CategoryColors['Procedures']);
        this.setTooltip(Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP);
        this.setHelpUrl(Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL);
        this.arguments_ = [];
        this.setStatements_(!0);
        this.statementConnection_ = null
    },
    setStatements_: Blockly.Blocks.procedures_defnoreturn.setStatements_,
    updateParams_: Blockly.Blocks.procedures_defnoreturn.updateParams_,
    mutationToDom: Blockly.Blocks.procedures_defnoreturn.mutationToDom,
    domToMutation: Blockly.Blocks.procedures_defnoreturn.domToMutation,
    decompose: Blockly.Blocks.procedures_defnoreturn.decompose,
    compose: Blockly.Blocks.procedures_defnoreturn.compose,
    getProcedureDef: function () {
        return [this.getFieldValue("NAME"), this.arguments_, !0]
    },
    getVars: Blockly.Blocks.procedures_defnoreturn.getVars,
    renameVar: Blockly.Blocks.procedures_defnoreturn.renameVar,
    customContextMenu: Blockly.Blocks.procedures_defnoreturn.customContextMenu,
    callType_: "procedures_callreturn"
};
Blockly.Blocks.procedures_mutatorcontainer = {
    init: function () {
        this.appendDummyInput().appendField(Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE);
        this.appendStatementInput("STACK");
        this.appendDummyInput("STATEMENT_INPUT").appendField(Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS).appendField(new Blockly.FieldCheckbox("TRUE"), "STATEMENTS");
        this.setColour(CategoryColors['Procedures']);
        this.setTooltip(Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP);
        this.contextMenu = !1
    }
};
Blockly.Blocks.procedures_mutatorarg = {
    init: function () {
        var a = new Blockly.FieldTextInput("x", this.validator_);
        this.appendDummyInput().appendField(Blockly.Msg.PROCEDURES_MUTATORARG_TITLE).appendField(a, "NAME");
        this.setPreviousStatement(!0);
        this.setNextStatement(!0);
        this.setColour(CategoryColors['Procedures']);
        this.setTooltip(Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP);
        this.contextMenu = !1;
        a.onFinishEditing_ = this.createNewVar_;
        a.onFinishEditing_("x")
    },
    validator_: function (a) {
        return (a = a.replace(/[\s\xa0]+/g, " ").replace(/^ | $/g, "")) || null
    },
    createNewVar_: function (a) {
        var b = this.sourceBlock_;
        b && b.workspace && b.workspace.options && b.workspace.options.parentWorkspace && b.workspace.options.parentWorkspace.createVariable(a)
    }
};
Blockly.Blocks.procedures_callnoreturn = {
    init: function () {
        this.appendDummyInput("TOPROW").appendField(this.id, "NAME");
        this.setPreviousStatement(!0);
        this.setNextStatement(!0);
        this.setColour(CategoryColors['Procedures']);
        this.setHelpUrl(Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL);
        this.arguments_ = [];
        this.quarkConnections_ = {};
        this.quarkIds_ = null
    },
    getProcedureCall: function () {
        return this.getFieldValue("NAME")
    },
    renameProcedure: function (a, b) {
        Blockly.Names.equals(a, this.getProcedureCall()) && (this.setFieldValue(b, "NAME"),
            this.setTooltip((this.outputConnection ? Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP : Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP).replace("%1", b)))
    },
    setProcedureParameters_: function (a, b) {
        var c = Blockly.Procedures.getDefinition(this.getProcedureCall(), this.workspace)
            , e = c && c.mutator ;
        e || (this.quarkConnections_ = {},
            this.quarkIds_ = null);
        if (b)
            if (goog.array.equals(this.arguments_, a))
                this.quarkIds_ = b;
            else {
                if (b.length != a.length)
                    throw "Error: paramNames and paramIds must be the same length.";
                this.setCollapsed(!1);
                this.quarkIds_ || (this.quarkConnections_ = {},
                    a.join("\n") == this.arguments_.join("\n") ? this.quarkIds_ = b : this.quarkIds_ = []);
                c = this.rendered;
                this.rendered = !1;
                for (var d = 0; d < this.arguments_.length; d++) {
                    var f = this.getInput("ARG" + d);
                    f && (f = f.connection.targetConnection,
                        this.quarkConnections_[this.quarkIds_[d]] = f,
                        e && f && -1 == b.indexOf(this.quarkIds_[d]) && (f.disconnect(),
                            f.getSourceBlock().bumpNeighbours_()))
                }
                this.arguments_ = [].concat(a);
                this.updateShape_();
                if (this.quarkIds_ = b)
                    for (d = 0; d < this.arguments_.length; d++)
                        e = this.quarkIds_[d],
                            e in this.quarkConnections_ && (f = this.quarkConnections_[e],
                                Blockly.icons.MutatorIcon.reconnect(f, this, "ARG" + d) || delete this.quarkConnections_[e]);
                (this.rendered = c) && this.render()
            }
    },
    updateShape_: function () {
        for (var a = 0; a < this.arguments_.length; a++) {
            var b = this.getField("ARGNAME" + a);
            if (b) {
                Blockly.Events.disable();
                try {
                    b.setValue(this.arguments_[a])
                } finally {
                    Blockly.Events.enable()
                }
            } else
                b = new Blockly.FieldLabel(this.arguments_[a]),
                    this.appendValueInput("ARG" + a).setAlign(Blockly.ALIGN_RIGHT).appendField(b, "ARGNAME" + a).init()
        }
        for (; this.getInput("ARG" + a);)
            this.removeInput("ARG" + a),
                a++;
        if (a = this.getInput("TOPROW"))
            this.arguments_.length ? this.getField("WITH") || (a.appendField(Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS, "WITH"),
                a.init()) : this.getField("WITH") && a.removeField("WITH")
    },
    mutationToDom: function () {
        var a = document.createElement("mutation");
        a.setAttribute("name", this.getProcedureCall());
        for (var b = 0; b < this.arguments_.length; b++) {
            var c = document.createElement("arg");
            c.setAttribute("name", this.arguments_[b]);
            a.appendChild(c)
        }
        return a
    },
    domToMutation: function (a) {
        var b = a.getAttribute("name");
        this.renameProcedure(this.getProcedureCall(), b);
        b = [];
        for (var c = [], e = 0, d; d = a.childNodes[e]; e++)
            "arg" == d.nodeName.toLowerCase() && (b.push(d.getAttribute("name")),
                c.push(d.getAttribute("paramId")));
        this.setProcedureParameters_(b, c)
    },
    renameVar: function (a, b) {
        for (var c = 0; c < this.arguments_.length; c++)
            Blockly.Names.equals(a, this.arguments_[c]) && (this.arguments_[c] = b,
                this.getField("ARGNAME" + c).setValue(b))
    },
    onchange: function (a) {
        if (this.workspace && !this.workspace.isFlyout)
            if (a.type == Blockly.Events.CREATE && -1 != a.ids.indexOf(this.id)) {
                var b = this.getProcedureCall();
                b = Blockly.Procedures.getDefinition(b, this.workspace);
                !b || b.type == this.defType_ && JSON.stringify(b.arguments_) == JSON.stringify(this.arguments_) || (b = null);
                if (!b) {
                    Blockly.Events.setGroup(a.group);
                    a = Blockly.dom.createDom("xml");
                    b = Blockly.dom.createDom("block");
                    b.setAttribute("type", this.defType_);
                    var c = this.getRelativeToSurfaceXY()
                        , e = c.y + 2 * Blockly.SNAP_RADIUS;
                    b.setAttribute("x", c.x + Blockly.SNAP_RADIUS * (this.RTL ? -1 : 1));
                    b.setAttribute("y", e);
                    c = this.mutationToDom();
                    b.appendChild(c);
                    c = Blockly.dom.createDom("field");
                    c.setAttribute("name", "NAME");
                    c.appendChild(document.createTextNode(this.getProcedureCall()));
                    b.appendChild(c);
                    a.appendChild(b);
                    Blockly.Xml.domToWorkspace(a, this.workspace);
                    Blockly.Events.setGroup(!1)
                }
            } else
                a.type == Blockly.Events.DELETE && (b = this.getProcedureCall(),
                    b = Blockly.Procedures.getDefinition(b, this.workspace),
                    b || (Blockly.Events.setGroup(a.group),
                        this.dispose(!0, !1),
                        Blockly.Events.setGroup(!1)))
    },
    customContextMenu: function (a) {
        var b = {
            enabled: !0
        };
        b.text = Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF;
        var c = this.getProcedureCall()
            , e = this.workspace;
        b.callback = function () {
            var a = Blockly.Procedures.getDefinition(c, e);
            a && a.select()
        }
            ;
        a.push(b)
    },
    defType_: "procedures_defnoreturn"
};
Blockly.Blocks.procedures_callreturn = {
    init: function () {
        this.appendDummyInput("TOPROW").appendField("", "NAME");
        this.setOutput(!0);
        this.setColour(CategoryColors['Procedures']);
        this.setHelpUrl(Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL);
        this.arguments_ = [];
        this.quarkConnections_ = {};
        this.quarkIds_ = null
    },
    getProcedureCall: Blockly.Blocks.procedures_callnoreturn.getProcedureCall,
    renameProcedure: Blockly.Blocks.procedures_callnoreturn.renameProcedure,
    setProcedureParameters_: Blockly.Blocks.procedures_callnoreturn.setProcedureParameters_,
    updateShape_: Blockly.Blocks.procedures_callnoreturn.updateShape_,
    mutationToDom: Blockly.Blocks.procedures_callnoreturn.mutationToDom,
    domToMutation: Blockly.Blocks.procedures_callnoreturn.domToMutation,
    renameVar: Blockly.Blocks.procedures_callnoreturn.renameVar,
    onchange: Blockly.Blocks.procedures_callnoreturn.onchange,
    customContextMenu: Blockly.Blocks.procedures_callnoreturn.customContextMenu,
    defType_: "procedures_defreturn"
};
Blockly.Blocks.procedures_ifreturn = {
    init: function () {
        this.appendValueInput("CONDITION").setCheck("Boolean").appendField(Blockly.Msg.CONTROLS_IF_MSG_IF);
        this.appendValueInput("VALUE").appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);
        this.setInputsInline(!0);
        this.setPreviousStatement(!0);
        this.setNextStatement(!0);
        this.setColour(CategoryColors['Procedures']);
        this.setTooltip(Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP);
        this.setHelpUrl(Blockly.Msg.PROCEDURES_IFRETURN_HELPURL);
        this.hasReturnValue_ = !0
    },
    mutationToDom: function () {
        var a = document.createElement("mutation");
        a.setAttribute("value", Number(this.hasReturnValue_));
        return a
    },
    domToMutation: function (a) {
        this.hasReturnValue_ = 1 == a.getAttribute("value");
        this.hasReturnValue_ || (this.removeInput("VALUE"),
            this.appendDummyInput("VALUE").appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN))
    },
    onchange: function (a) {
        if (!this.workspace.isDragging()) {
            a = !1;
            var b = this;
            do {
                if (-1 != this.FUNCTION_TYPES.indexOf(b.type)) {
                    a = !0;
                    break
                }
                b = b.getSurroundParent()
            } while (b); a ? ("procedures_defnoreturn" == b.type && this.hasReturnValue_ ? (this.removeInput("VALUE"),
                this.appendDummyInput("VALUE").appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN),
                this.hasReturnValue_ = !1) : "procedures_defreturn" != b.type || this.hasReturnValue_ || (this.removeInput("VALUE"),
                    this.appendValueInput("VALUE").appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN),
                    this.hasReturnValue_ = !0),
                this.setWarningText(null),
                this.isInFlyout || this.setDisabled(!1)) : (this.setWarningText(Blockly.Msg.PROCEDURES_IFRETURN_WARNING),
                    this.isInFlyout || this.getInheritedDisabled() || this.setDisabled(!0))
        }
    },
    FUNCTION_TYPES: ["procedures_defnoreturn", "procedures_defreturn"]
};

export default Blockly;