include "primitives.alh"

Diagram dynamic_trafficlight {
    name = "Dynamic Traffic Light"
    author = "Yentl Van Tendeloo"
}

Class manager {
    name = "Manager"
    default = True
    constructor_body = $
            Void function constructor(attributes : Element, parameters : Element):
                dict_add(attributes, "trafficlights", list_create())
                return !
        $

    {behaviour} CompositeState manager_main {
        name = "main"
        isInitial = True
        {composite_children} BasicState manager_main_start {
            name = "start"
            isInitial = True
        }
    }
}

transition (manager_main_start, manager_main_start) {
    name = "create"
    event = "create"

    {transition_raises} Raise {
        scope = "cd"
        event = "create_instance"
        parameter = $
                Element function raise(attributes : Element, parameters : Element):
                    Element result
                    result = list_create()
                    list_append(result, "trafficlights")
                    list_append(result, "TrafficLight")
                    list_append(result, read_root())
                    return result!
            $
    }
}

transition (manager_main_start, manager_main_start) {
    name = "created"
    event = "instance_created"

    script = $
            Void function script(attributes : Element, parameters : Element):
                list_append(attributes["trafficlights"], parameters[0])
                return!
        $
}

transition (manager_main_start, manager_main_start) {
    name = "delete"
    event = "delete"

    {transition_raises} Raise {
        scope = "cd"
        event = "delete_instance"
        parameter = $
                Element function raise(attributes : Element, parameters : Element):
                    Element result
                    result = list_create()
                    list_append(result, list_pop_final(attributes["trafficlights"]))
                    return result!
            $
    }
}

Class trafficlight {
    name = "TrafficLight"
    default = False
    constructor_body = $
            Void function constructor(attributes : Element, parameters : Element):
                dict_add(attributes, "counter", 0)
                dict_add(attributes, "colour", "")
                return!
        $

    {behaviour} CompositeState trafficlight_main {
        name = "main"
        isInitial = True
        {composite_children} BasicState trafficlight_main_off {
            name = "off"
            isInitial = True
        }

        {composite_children} ParallelState trafficlight_main_main {
            name = "main"
            isInitial = False

            {onExitRaise} Raise {
                event = "displayNone"
            }

            {parallel_children} CompositeState trafficlight_main_main_trafficlight {
                name = "trafficlight"
                isInitial = False

                {composite_children} CompositeState trafficlight_main_main_trafficlight_normal {
                    name = "normal"
                    isInitial = True

                    onExitScript = $
                            Void function onexit(attributes : Element):
                                dict_overwrite(attributes, "colour", "")
                                return!
                        $

                    {composite_children} BasicState trafficlight_main_main_trafficlight_normal_red {
                        name = "red"
                        isInitial = True

                        onEntryScript = $
                                Void function onentry(attributes : Element):
                                    dict_overwrite(attributes, "counter", 60)
                                    dict_overwrite(attributes, "colour", "red")
                                    return!
                            $

                        {onEntryRaise} Raise {
                            event = "displayRed"
                        }
                        {onEntryRaise} Raise {
                            event = "resetTimer"
                        }
                    }

                    {composite_children} BasicState trafficlight_main_main_trafficlight_normal_green {
                        name = "green"
                        isInitial = False

                        onEntryScript = $
                                Void function onentry(attributes : Element):
                                    dict_overwrite(attributes, "counter", 55)
                                    dict_overwrite(attributes, "colour", "green")
                                    return!
                            $

                        {onEntryRaise} Raise {
                            event = "displayGreen"
                        }
                        {onEntryRaise} Raise {
                            event = "resetTimer"
                        }
                    }

                    {composite_children} BasicState trafficlight_main_main_trafficlight_normal_yellow {
                        name = "yellow"
                        isInitial = False

                        onEntryScript = $
                                Void function onentry(attributes : Element):
                                    dict_overwrite(attributes, "colour", "")
                                    return!
                            $

                        {onEntryRaise} Raise {
                            event = "displayYellow"
                        }
                        {onEntryRaise} Raise {
                            event = "disableTimer"
                        }
                    }

                    {composite_children} HistoryState trafficlight_main_main_trafficlight_normal_hist {
                        name = "hist"
                    }
                }

                {composite_children} CompositeState trafficlight_main_main_trafficlight_interrupted {
                    {composite_children} BasicState trafficlight_main_main_trafficlight_interrupted_yellow {
                        name = "yellow"
                        isInitial = True

                        {onEntryRaise} Raise {
                            event = "displayYellow"
                        }
                    }

                    {composite_children} BasicState trafficlight_main_main_trafficlight_interrupted_black {
                        name = "black"
                        isInitial = False

                        {onEntryRaise} Raise {
                            event = "displayNone"
                        }
                    }
                }
            }

            {parallel_children} CompositeState trafficlight_main_main_timer {
                name = "timer"
                isInitial = False

                {composite_children} BasicState trafficlight_main_main_timer_disabled {
                    name = "disabled"
                    isInitial = False
                }

                {composite_children} CompositeState trafficlight_main_main_timer_running {
                    name = "running"
                    isInitial = True

                    {onExitRaise} Raise {
                        event = "updateTimerValue"
                        parameter = $
                                Element function parameter(attributes : Element):
                                    return -1!
                            $
                    }

                    {composite_children} BasicState trafficlight_main_main_timer_running_decidingcolor {
                        name = "decidingcolor"
                        isInitial = True
                    }

                    {composite_children} BasicState trafficlight_main_main_timer_running_green {
                        name = "green"
                        isInitial = False

                        {onEntryRaise} Raise {
                            event = "updateTimerValue"
                            parameter = $
                                    Element function raise(attributes : Element):
                                        return attributes["counter"]!
                                $
                        }
                    }

                    {composite_children} BasicState trafficlight_main_main_timer_running_red {
                        name = "red"
                        isInitial = False

                        {onEntryRaise} Raise {
                            event = "updateTimerValue"
                            parameter = $
                                    Element function raise(attributes : Element):
                                        return attributes["counter"]!
                                $
                        }
                    }
                }
            }
        }
    }
}

transition (trafficlight_main_off, trafficlight_main_main) {
    name = "toggle"
    event = "toggle"
}

transition (trafficlight_main_main, trafficlight_main_off) {
    name = "toggle"
    event = "toggle"
}

transition (trafficlight_main_main_trafficlight_normal, trafficlight_main_main_trafficlight_interrupted) {
    name = "police_interrupt / disableTimer"
    event = "police_interrupt"

    {transition_raises} Raise {
        event = "disableTimer"
    }
}

transition (trafficlight_main_main_trafficlight_interrupted, trafficlight_main_main_trafficlight_normal_hist) {
    name = "police_interrupt / enableTimer"
    event = "police_interrupt"

    {transition_raises} Raise {
        event = "enableTimer"
    }
}

transition (trafficlight_main_main_trafficlight_normal_red, trafficlight_main_main_trafficlight_normal_green) {
    name = "after 60s"
    after = $
            Float function after(attributes : Element):
                return 60.0!
        $
}

transition (trafficlight_main_main_trafficlight_normal_green, trafficlight_main_main_trafficlight_normal_yellow) {
    name = "after 55s"
    after = $
            Float function after(attributes : Element):
                return 55.0!
        $
}

transition (trafficlight_main_main_trafficlight_normal_yellow, trafficlight_main_main_trafficlight_normal_red) {
    name = "after 5s"
    after = $
            Float function after(attributes : Element):
                return 5.0!
        $

    {transition_raises} Raise {
        event = "enableTimer"
    }
}

transition (trafficlight_main_main_trafficlight_interrupted_yellow, trafficlight_main_main_trafficlight_interrupted_black) {
    name = "after 500ms"
    after = $
            Float function after(attributes : Element):
                return 0.5!
        $
}

transition (trafficlight_main_main_trafficlight_interrupted_black, trafficlight_main_main_trafficlight_interrupted_yellow) {
    name = "after 500ms"
    after = $
            Float function after(attributes : Element):
                return 0.5!
        $
}

transition (trafficlight_main_main_timer_disabled, trafficlight_main_main_timer_running) {
    name = "enableTimer"
    event = "enableTimer"
}

transition (trafficlight_main_main_timer_running, trafficlight_main_main_timer_disabled) {
    name = "disableTimer"
    event = "disableTimer"
}

transition (trafficlight_main_main_timer_running, trafficlight_main_main_timer_running) {
    name = "resetTimer"
    event = "resetTimer"
}

transition (trafficlight_main_main_timer_running_decidingcolor, trafficlight_main_main_timer_running_green) {
    name = "[green] / updateTimerColour"
    cond = $
            Boolean function cond(attributes : Element, parameters : Element):
                return value_eq(attributes["colour"], "green")!
        $

    {transition_raises} Raise {
        event = "updateTimerColour"
        parameter = $
                Element function param(attributes : Element, parameters : Element):
                    return "green"!
            $
    }
}

transition (trafficlight_main_main_timer_running_decidingcolor, trafficlight_main_main_timer_running_red) {
    name = "[red] / updateTimerColour"
    cond = $
            Boolean function cond(attributes : Element, parameters : Element):
                return value_eq(attributes["colour"], "red")!
        $

    {transition_raises} Raise {
        event = "updateTimerColour"
        parameter = $
                Element function param(attributes : Element, parameters : Element):
                    return "red"!
            $
    }
}

transition (trafficlight_main_main_timer_running_red, trafficlight_main_main_timer_running_red) {
    name = "after 1s / counter -= 1"
    after = $
            Float function after(attributes : Element):
                return 1.0!
        $
    script = $
            Void function script(attributes : Element, parameters : Element):
                dict_overwrite(attributes, "counter", integer_subtraction(attributes["counter"], 1))
                return!
        $
}

transition (trafficlight_main_main_timer_running_green, trafficlight_main_main_timer_running_green) {
    name = "after 1s / counter -= 1"
    after = $
            Float function after(attributes : Element):
                return 1.0!
        $
    script = $
            Void function script(attributes : Element, parameters : Element):
                dict_overwrite(attributes, "counter", integer_subtraction(attributes["counter"], 1))
                return!
        $
}
