include "primitives.alh"
include "modelling.alh"
include "object_operations.alh"

Composite schedule {
    {Contains} Success success {}
    {Contains} Failure failure {}

    {Contains} ForAll update_blocks {
        LHS {
            Pre_abstract/Block pre_update_0 {
                label = "0"
            }
            Pre_rendered/Group pre_update_1 {
                label = "1"
            }
            Pre_TracabilityLink (pre_update_0, pre_update_1){
                label = "2"
            }
        }
        RHS {
            Post_abstract/Block post_update_0 {
                label = "0"
            }
            Post_rendered/Group post_update_1 {
                label = "1"
                value___asid = $
                    String function value(model : Element, name : String, mapping : Element):
                        // Update the mapping!
                        if (read_nr_out(string_split(mapping["0"], "/")) > 1):
                            return list_read(string_split(mapping["0"], "/"), 1)!
                        else:
                            return mapping["0"]!
                    $
                value_x = $
                    Integer function value(model : Element, name : String, mapping : Element):
                        return read_attribute(model, name, "x")!
                    $
                value_y = $
                    Integer function value(model : Element, name : String, mapping : Element):
                        return read_attribute(model, name, "y")!
                    $
            }
            Post_TracabilityLink (post_update_0, post_update_1){
                label = "2"
            }
        }
    }

    {Contains} ForAll render_blocks {
        LHS {
            Pre_abstract/Block pre_block_0 {
                label = "0"
            }

            constraint = $
                Boolean function constraint(model : Element, mapping : Element):
                    Element trace_links
                    trace_links = allOutgoingAssociationInstances(model, mapping["0"], "TracabilityLink")
                    if (read_nr_out(trace_links) > 0):
                        log("Block already connected; ignoring!")
                        return False!
                    else:
                        return True!
                $
        }
        RHS {
            Post_abstract/Block post_block_0 {
                label = "0"
            }
            Post_rendered/Group post_block_1 {
                label = "1"
                value___asid = $
                    String function value(model : Element, name : String, mapping : Element):
                        if (list_len(string_split(mapping["0"], "/")) > 1):
                            return list_read(string_split(mapping["0"], "/"), 1)!
                        else:
                            return mapping["0"]!
                    $
                value_x = $
                    Integer function value(model : Element, name : String, mapping : Element):
                        return 0!
                    $
                value_y = $
                    Integer function value(model : Element, name : String, mapping : Element):
                        return 0!
                    $
            }
            Post_rendered/Rectangle post_block_2 {
                label = "2"
                value_x = $
                    Integer function value(model : Element, name : String, mapping : Element):
                        return 0!
                    $
                value_y = $
                    Integer function value(model : Element, name : String, mapping : Element):
                        return 0!
                    $
                value_width = $
                    Integer function value(model : Element, name : String, mapping : Element):
                        return 30!
                    $
                value_height = $
                    Integer function value(model : Element, name : String, mapping : Element):
                        return 30!
                    $
                value_lineWidth = $
                    Integer function value(model : Element, name : String, mapping : Element):
                        return 2!
                    $
                value_lineColour = $
                    String function value(model : Element, name : String, mapping : Element):
                        return "black"!
                    $
                value_fillColour = $
                    String function value(model : Element, name : String, mapping : Element):
                        return "white"!
                    $
            }
            Post_rendered/Text post_block_3 {
                label = "3"
                value_x = $
                    Integer function value(model : Element, name : String, mapping : Element):
                        return 10!
                    $
                value_y = $
                    Integer function value(model : Element, name : String, mapping : Element):
                        return 10!
                    $
                value_lineWidth = $
                    Integer function value(model : Element, name : String, mapping : Element):
                        return 1!
                    $
                value_lineColour = $
                    String function value(model : Element, name : String, mapping : Element):
                        return "black"!
                    $
                value_text = $
                    String function value(model : Element, name : String, mapping : Element):
                        String type
                        type = read_type(model, mapping["0"])
                        if (type == "abstract/AdditionBlock"):
                            return "+"!
                        elif (type == "abstract/NegatorBlock"):
                            return "-"!
                        elif (type == "abstract/ConstantBlock"):
                            return "c"!
                        elif (type == "abstract/MultiplyBlock"):
                            return "*"!
                        elif (type == "abstract/InverseBlock"):
                            return "/"!
                        elif (type == "abstract/DerivatorBlock"):
                            return "d/dx"!
                        elif (type == "abstract/IntegratorBlock"):
                            return "1/s"!
                        elif (type == "abstract/DelayBlock"):
                            return "DELAY"!
                        elif (type == "abstract/ProbeBlock"):
                            return "PROBE"!
                        else:
                            return ("Unknown type: " + type)!
                    $
            }
            Post_rendered/contains (post_block_1, post_block_2) {
                label = "4"
            }
            Post_rendered/contains (post_block_1, post_block_3) {
                label = "5"
            }

            Post_TracabilityLink (post_block_0, post_block_1) {
                label = "6"
            }
        }
    }

    {Contains} ForAll remove_connections {
        LHS {
            Pre_rendered/Line {
                label = "0"
            }
        }
        RHS {
        }
    }

    {Contains} ForAll render_connections {
        LHS {
            Pre_abstract/Block pre_conn_0 {
                label = "0"
            }

            Pre_abstract/Block pre_conn_1 {
                label = "1"
            }

            Pre_abstract/Link (pre_conn_0, pre_conn_1){
                label = "2"
            }

            Pre_rendered/Group pre_conn_3 {
                label = "3"
            }

            Pre_rendered/Group pre_conn_4 {
                label = "4"
            }

            Pre_TracabilityLink (pre_conn_0, pre_conn_3) {
                label = "5"
            }
            Pre_TracabilityLink (pre_conn_1, pre_conn_4) {
                label = "6"
            }
        }
        RHS {
            Post_abstract/Block post_conn_0 {
                label = "0"
            }

            Post_abstract/Block post_conn_1 {
                label = "1"
            }

            Post_abstract/Link (post_conn_0, post_conn_1){
                label = "2"
            }

            Post_rendered/Group post_conn_3 {
                label = "3"
            }

            Post_rendered/Group post_conn_4 {
                label = "4"
            }

            Post_TracabilityLink (post_conn_0, post_conn_3) {
                label = "5"
            }
            Post_TracabilityLink (post_conn_1, post_conn_4) {
                label = "6"
            }

            Post_rendered/Line {
                label = "7"
                value___asid = $
                    String function value(model : Element, name : String, mapping : Element):
                        if (list_len(string_split(mapping["2"], "/")) > 1):
                            return list_read(string_split(mapping["2"], "/"), 1)!
                        else:
                            return mapping["2"]!
                    $
                value_x = $
                    Integer function value(model : Element, name : String, mapping : Element):
                        return read_attribute(model, mapping["3"], "x")!
                    $
                value_y = $
                    Integer function value(model : Element, name : String, mapping : Element):
                        return read_attribute(model, mapping["3"], "y")!
                    $
                value_lineWidth = $
                    Integer function value(model : Element, name : String, mapping : Element):
                        return 1!
                    $
                value_lineColour = $
                    String function value(model : Element, name : String, mapping : Element):
                        if (read_type(model, name) == "ICLink"):
                            return "red"!
                        else:
                            return "black"!
                    $
                value_targetX = $
                    Integer function value(model : Element, name : String, mapping : Element):
                        return read_attribute(model, mapping["4"], "x")!
                    $
                value_targetY = $
                    Integer function value(model : Element, name : String, mapping : Element):
                        return read_attribute(model, mapping["4"], "y")!
                    $
            }
        }
    }
}

Initial (schedule, update_blocks) {}

OnSuccess (update_blocks, render_blocks) {}
OnFailure (update_blocks, render_blocks) {}

OnSuccess (render_blocks, remove_connections) {}
OnFailure (render_blocks, remove_connections) {}

OnSuccess (remove_connections, render_connections) {}
OnFailure (remove_connections, render_connections) {}

OnSuccess (render_connections, success) {}
OnFailure (render_connections, success) {}
