/**
 * Statechart compiler by Glenn De Jonghe
 * Javascript generator by Joeri Exelmans
 * 
 * Date:   Tue Mar 01 17:22:48 2016
 * 
 * Model author: Simon Van Mierlo
 * Model name:   ParticleInteraction
 * Model description:
    Visualization of Particle Interaction Simulation
 */

// put everything in an object (serves as "namespace")
ParticleInteraction = {};

// closure scope
(function() {

// The actual constructor
var MainApp = function(controller, resolution) {
    MainApp.prototype.commonConstructor.call(this,controller);
    
    // constructor body (user-defined)
    this.nr_of_fields = 0
    this.resolution = resolution
    ui.bind_event(ui.window, ui.EVENTS.WINDOW_CLOSE, this.controller, 'window_close');
};


MainApp.prototype = new RuntimeClassBase();

// Unique IDs for all statechart nodes
MainApp.prototype.Root = 0;
MainApp.prototype.Root_main = 1;
MainApp.prototype.Root_main_main_behaviour = 2;
MainApp.prototype.Root_main_creating_behaviour = 3;
MainApp.prototype.Root_main_deleting_behaviour = 4;
MainApp.prototype.Root_main_main_behaviour_initializing = 5;
MainApp.prototype.Root_main_main_behaviour_running = 6;
MainApp.prototype.Root_main_creating_behaviour_waiting = 7;
MainApp.prototype.Root_main_creating_behaviour_creating = 8;
MainApp.prototype.Root_main_deleting_behaviour_waiting = 9;
MainApp.prototype.Root_main_deleting_behaviour_deleting = 10;
MainApp.prototype.Root_stopped = 11;

// Statechart enter/exit action method(s) :

MainApp.prototype.enter_Root_main = function() {
    this.current_state[this.Root].push(this.Root_main);
};

MainApp.prototype.exit_Root_main = function() {
    this.exit_Root_main_main_behaviour();
    this.exit_Root_main_creating_behaviour();
    this.exit_Root_main_deleting_behaviour();
    this.current_state[this.Root] = new Array();
};

MainApp.prototype.enter_Root_main_main_behaviour = function() {
    this.current_state[this.Root_main].push(this.Root_main_main_behaviour);
};

MainApp.prototype.exit_Root_main_main_behaviour = function() {
    if (this.current_state[this.Root_main_main_behaviour].indexOf(this.Root_main_main_behaviour_initializing) !== -1) {
        this.exit_Root_main_main_behaviour_initializing();
    }
    if (this.current_state[this.Root_main_main_behaviour].indexOf(this.Root_main_main_behaviour_running) !== -1) {
        this.exit_Root_main_main_behaviour_running();
    }
    this.current_state[this.Root_main] = new Array();
};

MainApp.prototype.enter_Root_main_creating_behaviour = function() {
    this.current_state[this.Root_main].push(this.Root_main_creating_behaviour);
};

MainApp.prototype.exit_Root_main_creating_behaviour = function() {
    if (this.current_state[this.Root_main_creating_behaviour].indexOf(this.Root_main_creating_behaviour_waiting) !== -1) {
        this.exit_Root_main_creating_behaviour_waiting();
    }
    if (this.current_state[this.Root_main_creating_behaviour].indexOf(this.Root_main_creating_behaviour_creating) !== -1) {
        this.exit_Root_main_creating_behaviour_creating();
    }
    this.current_state[this.Root_main] = new Array();
};

MainApp.prototype.enter_Root_main_deleting_behaviour = function() {
    this.current_state[this.Root_main].push(this.Root_main_deleting_behaviour);
};

MainApp.prototype.exit_Root_main_deleting_behaviour = function() {
    if (this.current_state[this.Root_main_deleting_behaviour].indexOf(this.Root_main_deleting_behaviour_waiting) !== -1) {
        this.exit_Root_main_deleting_behaviour_waiting();
    }
    if (this.current_state[this.Root_main_deleting_behaviour].indexOf(this.Root_main_deleting_behaviour_deleting) !== -1) {
        this.exit_Root_main_deleting_behaviour_deleting();
    }
    this.current_state[this.Root_main] = new Array();
};

MainApp.prototype.enter_Root_main_main_behaviour_initializing = function() {
    this.addEvent(new Event("create_field", null, []));
    this.current_state[this.Root_main_main_behaviour].push(this.Root_main_main_behaviour_initializing);
};

MainApp.prototype.exit_Root_main_main_behaviour_initializing = function() {
    this.current_state[this.Root_main_main_behaviour] = new Array();
};

MainApp.prototype.enter_Root_main_main_behaviour_running = function() {
    this.current_state[this.Root_main_main_behaviour].push(this.Root_main_main_behaviour_running);
};

MainApp.prototype.exit_Root_main_main_behaviour_running = function() {
    this.current_state[this.Root_main_main_behaviour] = new Array();
};

MainApp.prototype.enter_Root_main_creating_behaviour_waiting = function() {
    this.current_state[this.Root_main_creating_behaviour].push(this.Root_main_creating_behaviour_waiting);
};

MainApp.prototype.exit_Root_main_creating_behaviour_waiting = function() {
    this.current_state[this.Root_main_creating_behaviour] = new Array();
};

MainApp.prototype.enter_Root_main_creating_behaviour_creating = function() {
    this.current_state[this.Root_main_creating_behaviour].push(this.Root_main_creating_behaviour_creating);
};

MainApp.prototype.exit_Root_main_creating_behaviour_creating = function() {
    this.current_state[this.Root_main_creating_behaviour] = new Array();
};

MainApp.prototype.enter_Root_main_deleting_behaviour_waiting = function() {
    this.current_state[this.Root_main_deleting_behaviour].push(this.Root_main_deleting_behaviour_waiting);
};

MainApp.prototype.exit_Root_main_deleting_behaviour_waiting = function() {
    this.current_state[this.Root_main_deleting_behaviour] = new Array();
};

MainApp.prototype.enter_Root_main_deleting_behaviour_deleting = function() {
    this.current_state[this.Root_main_deleting_behaviour].push(this.Root_main_deleting_behaviour_deleting);
};

MainApp.prototype.exit_Root_main_deleting_behaviour_deleting = function() {
    this.current_state[this.Root_main_deleting_behaviour] = new Array();
};

MainApp.prototype.enter_Root_stopped = function() {
    ui.close_window(ui.window);
    this.current_state[this.Root].push(this.Root_stopped);
};

MainApp.prototype.exit_Root_stopped = function() {
    this.current_state[this.Root] = new Array();
};

// Statechart enter/exit default method(s) :

MainApp.prototype.enterDefault_Root_main = function() {
    this.enter_Root_main();
    this.enterDefault_Root_main_main_behaviour();
    this.enterDefault_Root_main_creating_behaviour();
    this.enterDefault_Root_main_deleting_behaviour();
};

MainApp.prototype.enterDefault_Root_main_main_behaviour = function() {
    this.enter_Root_main_main_behaviour();
    this.enter_Root_main_main_behaviour_initializing();
};

MainApp.prototype.enterDefault_Root_main_creating_behaviour = function() {
    this.enter_Root_main_creating_behaviour();
    this.enter_Root_main_creating_behaviour_waiting();
};

MainApp.prototype.enterDefault_Root_main_deleting_behaviour = function() {
    this.enter_Root_main_deleting_behaviour();
    this.enter_Root_main_deleting_behaviour_waiting();
};

// Statechart transitions :

MainApp.prototype.transition_Root = function(event) {
    var catched = false;
    if (!catched) {
        if (this.current_state[this.Root][0] === this.Root_main) {
            catched = this.transition_Root_main(event);
        }
        else if (this.current_state[this.Root][0] === this.Root_stopped) {
            catched = this.transition_Root_stopped(event);
        }
    }
    return catched;
};

MainApp.prototype.transition_Root_main = function(event) {
    var catched = false;
    var enableds = new Array();
    if (event.name === "stop") {
        enableds.push(1);
    }
    
    if (enableds.length > 1) {
        console.log("Runtime warning : indeterminism detected in a transition from node Root_main. Only the first in document order enabled transition is executed.")
    }
    
    if (enableds.length > 0) {
        var enabled = enableds[0];
        if (enabled === 1) {
            this.exit_Root_main();
            this.enter_Root_stopped();
        }
        catched = true;
    }
    
    if (!catched) {
        catched = this.transition_Root_main_main_behaviour(event) || catched
        catched = this.transition_Root_main_creating_behaviour(event) || catched
        catched = this.transition_Root_main_deleting_behaviour(event) || catched
    }
    return catched;
};

MainApp.prototype.transition_Root_main_main_behaviour = function(event) {
    var catched = false;
    if (!catched) {
        if (this.current_state[this.Root_main_main_behaviour][0] === this.Root_main_main_behaviour_initializing) {
            catched = this.transition_Root_main_main_behaviour_initializing(event);
        }
        else if (this.current_state[this.Root_main_main_behaviour][0] === this.Root_main_main_behaviour_running) {
            catched = this.transition_Root_main_main_behaviour_running(event);
        }
    }
    return catched;
};

MainApp.prototype.transition_Root_main_main_behaviour_initializing = function(event) {
    var catched = false;
    var enableds = new Array();
    enableds.push(1);
    
    if (enableds.length > 1) {
        console.log("Runtime warning : indeterminism detected in a transition from node Root_main_main_behaviour_initializing. Only the first in document order enabled transition is executed.")
    }
    
    if (enableds.length > 0) {
        var enabled = enableds[0];
        if (enabled === 1) {
            this.exit_Root_main_main_behaviour_initializing();
            this.enter_Root_main_main_behaviour_running();
        }
        catched = true;
    }
    
    return catched;
};

MainApp.prototype.transition_Root_main_main_behaviour_running = function(event) {
    var catched = false;
    var enableds = new Array();
    if (event.name === "field_created") {
        enableds.push(1);
    }
    
    if (event.name === "field_deleted") {
        if (this.nr_of_fields > 1) {
            enableds.push(2);
        }
    }
    
    if (event.name === "field_deleted") {
        if (this.nr_of_fields == 1) {
            enableds.push(3);
        }
    }
    
    if (enableds.length > 1) {
        console.log("Runtime warning : indeterminism detected in a transition from node Root_main_main_behaviour_running. Only the first in document order enabled transition is executed.")
    }
    
    if (enableds.length > 0) {
        var enabled = enableds[0];
        if (enabled === 1) {
            this.exit_Root_main_main_behaviour_running();
            this.nr_of_fields += 1
            this.enter_Root_main_main_behaviour_running();
        }
        else if (enabled === 2) {
            this.exit_Root_main_main_behaviour_running();
            console.log('not stopped')
            this.nr_of_fields -= 1
            this.enter_Root_main_main_behaviour_running();
        }
        else if (enabled === 3) {
            this.exit_Root_main_main_behaviour_running();
            console.log('stopped')
            this.addEvent(new Event("stop", null, []));
            this.enter_Root_main_main_behaviour_running();
        }
        catched = true;
    }
    
    return catched;
};

MainApp.prototype.transition_Root_main_creating_behaviour = function(event) {
    var catched = false;
    if (!catched) {
        if (this.current_state[this.Root_main_creating_behaviour][0] === this.Root_main_creating_behaviour_waiting) {
            catched = this.transition_Root_main_creating_behaviour_waiting(event);
        }
        else if (this.current_state[this.Root_main_creating_behaviour][0] === this.Root_main_creating_behaviour_creating) {
            catched = this.transition_Root_main_creating_behaviour_creating(event);
        }
    }
    return catched;
};

MainApp.prototype.transition_Root_main_creating_behaviour_waiting = function(event) {
    var catched = false;
    var enableds = new Array();
    if (event.name === "create_field") {
        enableds.push(1);
    }
    
    if (enableds.length > 1) {
        console.log("Runtime warning : indeterminism detected in a transition from node Root_main_creating_behaviour_waiting. Only the first in document order enabled transition is executed.")
    }
    
    if (enableds.length > 0) {
        var enabled = enableds[0];
        if (enabled === 1) {
            this.exit_Root_main_creating_behaviour_waiting();
            this.object_manager.addEvent(new Event("create_instance", null, [this, 'fields','Field',this.resolution]));
            this.enter_Root_main_creating_behaviour_creating();
        }
        catched = true;
    }
    
    return catched;
};

MainApp.prototype.transition_Root_main_creating_behaviour_creating = function(event) {
    var catched = false;
    var enableds = new Array();
    if (event.name === "instance_created") {
        enableds.push(1);
    }
    
    if (enableds.length > 1) {
        console.log("Runtime warning : indeterminism detected in a transition from node Root_main_creating_behaviour_creating. Only the first in document order enabled transition is executed.")
    }
    
    if (enableds.length > 0) {
        var enabled = enableds[0];
        if (enabled === 1) {
            var parameters = event.parameters;
            
            var association_name = parameters[0];
            this.exit_Root_main_creating_behaviour_creating();
            this.object_manager.addEvent(new Event("start_instance", null, [this, association_name]));
            var send_event = new Event("set_association_name", null, [association_name]);
            this.object_manager.addEvent(new Event("narrow_cast", null, [this, association_name , send_event]));
            this.addEvent(new Event("field_created", null, []));
            this.enter_Root_main_creating_behaviour_waiting();
        }
        catched = true;
    }
    
    return catched;
};

MainApp.prototype.transition_Root_main_deleting_behaviour = function(event) {
    var catched = false;
    if (!catched) {
        if (this.current_state[this.Root_main_deleting_behaviour][0] === this.Root_main_deleting_behaviour_waiting) {
            catched = this.transition_Root_main_deleting_behaviour_waiting(event);
        }
        else if (this.current_state[this.Root_main_deleting_behaviour][0] === this.Root_main_deleting_behaviour_deleting) {
            catched = this.transition_Root_main_deleting_behaviour_deleting(event);
        }
    }
    return catched;
};

MainApp.prototype.transition_Root_main_deleting_behaviour_waiting = function(event) {
    var catched = false;
    var enableds = new Array();
    if (event.name === "delete_field") {
        enableds.push(1);
    }
    
    if (enableds.length > 1) {
        console.log("Runtime warning : indeterminism detected in a transition from node Root_main_deleting_behaviour_waiting. Only the first in document order enabled transition is executed.")
    }
    
    if (enableds.length > 0) {
        var enabled = enableds[0];
        if (enabled === 1) {
            var parameters = event.parameters;
            
            var association_name = parameters[0];
            this.exit_Root_main_deleting_behaviour_waiting();
            this.object_manager.addEvent(new Event("delete_instance", null, [this, association_name]));
            this.enter_Root_main_deleting_behaviour_deleting();
        }
        catched = true;
    }
    
    return catched;
};

MainApp.prototype.transition_Root_main_deleting_behaviour_deleting = function(event) {
    var catched = false;
    var enableds = new Array();
    if (event.name === "instance_deleted") {
        enableds.push(1);
    }
    
    if (enableds.length > 1) {
        console.log("Runtime warning : indeterminism detected in a transition from node Root_main_deleting_behaviour_deleting. Only the first in document order enabled transition is executed.")
    }
    
    if (enableds.length > 0) {
        var enabled = enableds[0];
        if (enabled === 1) {
            this.exit_Root_main_deleting_behaviour_deleting();
            this.addEvent(new Event("field_deleted", null, []));
            this.enter_Root_main_deleting_behaviour_waiting();
        }
        catched = true;
    }
    
    return catched;
};

MainApp.prototype.transition_Root_stopped = function(event) {
    var catched = false;
    return catched;
};

// Execute transitions
MainApp.prototype.transition = function(event) {
    if (!event) event = new Event();
    this.state_changed = this.transition_Root(event);
};

// inState method for statechart
MainApp.prototype.inState = function(nodes) {
    for (var c in this.current_state) {
        if (!this.current_state.hasOwnProperty(c)) continue;
        var new_nodes = new Array();
        for (var n in nodes) {
            if (!nodes.hasOwnProperty(n)) continue;
            if (this.current_state[c].indexOf(nodes[n]) === -1) {
                new_nodes.push(nodes[n]);
            }
        }
        nodes = new_nodes;
        if (nodes.length === 0) {
            return true;
        }
    }
    return false;
};

MainApp.prototype.commonConstructor = function(controller) {
    if (!controller) controller = null;
    // Constructor part that is common for all constructors.
    RuntimeClassBase.call(this);
    
    // User defined input ports
    this.inports = new Object();
    this.controller = controller;
    this.object_manager = (controller == null ? null : controller.object_manager);
    this.current_state = new Object();
    this.history_state = new Object();
    
    // Initialize statechart
    this.current_state[this.Root] = new Array();
    this.current_state[this.Root_main] = new Array();
    this.current_state[this.Root_main_main_behaviour] = new Array();
    this.current_state[this.Root_main_creating_behaviour] = new Array();
    this.current_state[this.Root_main_deleting_behaviour] = new Array();
};

MainApp.prototype.start = function() {
    RuntimeClassBase.prototype.start.call(this);
    this.enterDefault_Root_main();
};

// put class in global diagram object
ParticleInteraction.MainApp = MainApp;

// The actual constructor
var Field = function(controller, resolution) {
    Field.prototype.commonConstructor.call(this,controller);
    
    // constructor body (user-defined)
    this.field_window = ui.new_window(resolution[0] * 1.28, resolution[1] * 1.28);
    this.canvas = ui.append_canvas(this.field_window, resolution[0], resolution[1], {'background':'#eee'});
    this.text = this.canvas.add_text(5, 10, '0.0', {})
    ui.bind_event(this.field_window, ui.EVENTS.WINDOW_CLOSE, this.controller, 'window_close');
    ui.bind_event(this.field_window, ui.EVENTS.KEY_PRESS, this.controller, 'key_press');
    
    this.particles = {}
    this.creates = []
    this.moves = []
    this.color_changes = []
    this.deletes = []
    this.new_particle_id = undefined
    
    this.positions = {}
    this.curr_positions = {}
};


Field.prototype = new RuntimeClassBase();

// Unique IDs for all statechart nodes
Field.prototype.Root = 0;
Field.prototype.Root_main = 1;
Field.prototype.Root_main_main_behaviour = 2;
Field.prototype.Root_main_creating_behaviour = 3;
Field.prototype.Root_main_listening_behaviour = 4;
Field.prototype.Root_main_main_behaviour_initializing = 5;
Field.prototype.Root_main_main_behaviour_running = 6;
Field.prototype.Root_main_creating_behaviour_idle = 7;
Field.prototype.Root_main_creating_behaviour_creating_particle = 8;
Field.prototype.Root_main_listening_behaviour_listening = 9;
Field.prototype.Root_stopped = 10;

// User defined destructor
Field.prototype.destructor = function() {
    ui.close_window(this.field_window);
    
};
// Statechart enter/exit action method(s) :

Field.prototype.enter_Root_main = function() {
    this.current_state[this.Root].push(this.Root_main);
};

Field.prototype.exit_Root_main = function() {
    this.exit_Root_main_main_behaviour();
    this.exit_Root_main_creating_behaviour();
    this.exit_Root_main_listening_behaviour();
    this.current_state[this.Root] = new Array();
};

Field.prototype.enter_Root_main_main_behaviour = function() {
    this.current_state[this.Root_main].push(this.Root_main_main_behaviour);
};

Field.prototype.exit_Root_main_main_behaviour = function() {
    if (this.current_state[this.Root_main_main_behaviour].indexOf(this.Root_main_main_behaviour_initializing) !== -1) {
        this.exit_Root_main_main_behaviour_initializing();
    }
    if (this.current_state[this.Root_main_main_behaviour].indexOf(this.Root_main_main_behaviour_running) !== -1) {
        this.exit_Root_main_main_behaviour_running();
    }
    this.current_state[this.Root_main] = new Array();
};

Field.prototype.enter_Root_main_creating_behaviour = function() {
    this.current_state[this.Root_main].push(this.Root_main_creating_behaviour);
};

Field.prototype.exit_Root_main_creating_behaviour = function() {
    if (this.current_state[this.Root_main_creating_behaviour].indexOf(this.Root_main_creating_behaviour_idle) !== -1) {
        this.exit_Root_main_creating_behaviour_idle();
    }
    if (this.current_state[this.Root_main_creating_behaviour].indexOf(this.Root_main_creating_behaviour_creating_particle) !== -1) {
        this.exit_Root_main_creating_behaviour_creating_particle();
    }
    this.current_state[this.Root_main] = new Array();
};

Field.prototype.enter_Root_main_listening_behaviour = function() {
    this.current_state[this.Root_main].push(this.Root_main_listening_behaviour);
};

Field.prototype.exit_Root_main_listening_behaviour = function() {
    if (this.current_state[this.Root_main_listening_behaviour].indexOf(this.Root_main_listening_behaviour_listening) !== -1) {
        this.exit_Root_main_listening_behaviour_listening();
    }
    this.current_state[this.Root_main] = new Array();
};

Field.prototype.enter_Root_main_main_behaviour_initializing = function() {
    this.current_state[this.Root_main_main_behaviour].push(this.Root_main_main_behaviour_initializing);
};

Field.prototype.exit_Root_main_main_behaviour_initializing = function() {
    this.current_state[this.Root_main_main_behaviour] = new Array();
};

Field.prototype.enter_Root_main_main_behaviour_running = function() {
    this.current_state[this.Root_main_main_behaviour].push(this.Root_main_main_behaviour_running);
};

Field.prototype.exit_Root_main_main_behaviour_running = function() {
    this.current_state[this.Root_main_main_behaviour] = new Array();
};

Field.prototype.enter_Root_main_creating_behaviour_idle = function() {
    this.current_state[this.Root_main_creating_behaviour].push(this.Root_main_creating_behaviour_idle);
};

Field.prototype.exit_Root_main_creating_behaviour_idle = function() {
    this.current_state[this.Root_main_creating_behaviour] = new Array();
};

Field.prototype.enter_Root_main_creating_behaviour_creating_particle = function() {
    this.current_state[this.Root_main_creating_behaviour].push(this.Root_main_creating_behaviour_creating_particle);
};

Field.prototype.exit_Root_main_creating_behaviour_creating_particle = function() {
    this.current_state[this.Root_main_creating_behaviour] = new Array();
};

Field.prototype.enter_Root_main_listening_behaviour_listening = function() {
    this.current_state[this.Root_main_listening_behaviour].push(this.Root_main_listening_behaviour_listening);
};

Field.prototype.exit_Root_main_listening_behaviour_listening = function() {
    this.current_state[this.Root_main_listening_behaviour] = new Array();
};

Field.prototype.enter_Root_stopped = function() {
    var send_event = new Event("delete_field", null, [this.association_name]);
    this.object_manager.addEvent(new Event("narrow_cast", null, [this, 'parent' , send_event]));
    this.current_state[this.Root].push(this.Root_stopped);
};

Field.prototype.exit_Root_stopped = function() {
    this.current_state[this.Root] = new Array();
};

// Statechart enter/exit default method(s) :

Field.prototype.enterDefault_Root_main = function() {
    this.enter_Root_main();
    this.enterDefault_Root_main_main_behaviour();
    this.enterDefault_Root_main_creating_behaviour();
    this.enterDefault_Root_main_listening_behaviour();
};

Field.prototype.enterDefault_Root_main_main_behaviour = function() {
    this.enter_Root_main_main_behaviour();
    this.enter_Root_main_main_behaviour_initializing();
};

Field.prototype.enterDefault_Root_main_creating_behaviour = function() {
    this.enter_Root_main_creating_behaviour();
    this.enter_Root_main_creating_behaviour_idle();
};

Field.prototype.enterDefault_Root_main_listening_behaviour = function() {
    this.enter_Root_main_listening_behaviour();
    this.enter_Root_main_listening_behaviour_listening();
};

// Statechart transitions :

Field.prototype.transition_Root = function(event) {
    var catched = false;
    if (!catched) {
        if (this.current_state[this.Root][0] === this.Root_main) {
            catched = this.transition_Root_main(event);
        }
        else if (this.current_state[this.Root][0] === this.Root_stopped) {
            catched = this.transition_Root_stopped(event);
        }
    }
    return catched;
};

Field.prototype.transition_Root_main = function(event) {
    var catched = false;
    var enableds = new Array();
    if (event.name === "stop") {
        enableds.push(1);
    }
    
    if (enableds.length > 1) {
        console.log("Runtime warning : indeterminism detected in a transition from node Root_main. Only the first in document order enabled transition is executed.")
    }
    
    if (enableds.length > 0) {
        var enabled = enableds[0];
        if (enabled === 1) {
            this.exit_Root_main();
            this.object_manager.addEvent(new Event("delete_instance", null, [this, 'particles']));
            this.enter_Root_stopped();
        }
        catched = true;
    }
    
    if (!catched) {
        catched = this.transition_Root_main_main_behaviour(event) || catched
        catched = this.transition_Root_main_creating_behaviour(event) || catched
        catched = this.transition_Root_main_listening_behaviour(event) || catched
    }
    return catched;
};

Field.prototype.transition_Root_main_main_behaviour = function(event) {
    var catched = false;
    if (!catched) {
        if (this.current_state[this.Root_main_main_behaviour][0] === this.Root_main_main_behaviour_initializing) {
            catched = this.transition_Root_main_main_behaviour_initializing(event);
        }
        else if (this.current_state[this.Root_main_main_behaviour][0] === this.Root_main_main_behaviour_running) {
            catched = this.transition_Root_main_main_behaviour_running(event);
        }
    }
    return catched;
};

Field.prototype.transition_Root_main_main_behaviour_initializing = function(event) {
    var catched = false;
    var enableds = new Array();
    if (event.name === "set_association_name") {
        enableds.push(1);
    }
    
    if (enableds.length > 1) {
        console.log("Runtime warning : indeterminism detected in a transition from node Root_main_main_behaviour_initializing. Only the first in document order enabled transition is executed.")
    }
    
    if (enableds.length > 0) {
        var enabled = enableds[0];
        if (enabled === 1) {
            var parameters = event.parameters;
            
            var association_name = parameters[0];
            this.exit_Root_main_main_behaviour_initializing();
            this.association_name = association_name
            this.enter_Root_main_main_behaviour_running();
        }
        catched = true;
    }
    
    return catched;
};

Field.prototype.transition_Root_main_main_behaviour_running = function(event) {
    var catched = false;
    var enableds = new Array();
    if (event.name === "window_close" && event.port === "ui") {
        var parameters = event.parameters;
        
        var window = parameters[0];
        if (window == this.field_window || window == ui.window) {
            enableds.push(1);
        }
    }
    
    if (enableds.length > 1) {
        console.log("Runtime warning : indeterminism detected in a transition from node Root_main_main_behaviour_running. Only the first in document order enabled transition is executed.")
    }
    
    if (enableds.length > 0) {
        var enabled = enableds[0];
        if (enabled === 1) {
            var parameters = event.parameters;
            
            var window = parameters[0];
            this.exit_Root_main_main_behaviour_running();
            this.addEvent(new Event("stop", null, []));
            this.enter_Root_main_main_behaviour_running();
        }
        catched = true;
    }
    
    return catched;
};

Field.prototype.transition_Root_main_creating_behaviour = function(event) {
    var catched = false;
    if (!catched) {
        if (this.current_state[this.Root_main_creating_behaviour][0] === this.Root_main_creating_behaviour_idle) {
            catched = this.transition_Root_main_creating_behaviour_idle(event);
        }
        else if (this.current_state[this.Root_main_creating_behaviour][0] === this.Root_main_creating_behaviour_creating_particle) {
            catched = this.transition_Root_main_creating_behaviour_creating_particle(event);
        }
    }
    return catched;
};

Field.prototype.transition_Root_main_creating_behaviour_idle = function(event) {
    var catched = false;
    var enableds = new Array();
    if (event.name === "create_particle") {
        enableds.push(1);
    }
    
    if (enableds.length > 1) {
        console.log("Runtime warning : indeterminism detected in a transition from node Root_main_creating_behaviour_idle. Only the first in document order enabled transition is executed.")
    }
    
    if (enableds.length > 0) {
        var enabled = enableds[0];
        if (enabled === 1) {
            var parameters = event.parameters;
            
            var new_particle_info = parameters[0];
            this.exit_Root_main_creating_behaviour_idle();
            this.object_manager.addEvent(new Event("create_instance", null, [this, "particles","Particle",this.canvas,new_particle_info[0],new_particle_info[1][0],new_particle_info[1][1],new_particle_info[2]]));
            this.new_particle_id = new_particle_info[0]
            this.enter_Root_main_creating_behaviour_creating_particle();
        }
        catched = true;
    }
    
    return catched;
};

Field.prototype.transition_Root_main_creating_behaviour_creating_particle = function(event) {
    var catched = false;
    var enableds = new Array();
    if (event.name === "instance_created") {
        enableds.push(1);
    }
    
    if (enableds.length > 1) {
        console.log("Runtime warning : indeterminism detected in a transition from node Root_main_creating_behaviour_creating_particle. Only the first in document order enabled transition is executed.")
    }
    
    if (enableds.length > 0) {
        var enabled = enableds[0];
        if (enabled === 1) {
            var parameters = event.parameters;
            
            var association_name = parameters[0];
            this.exit_Root_main_creating_behaviour_creating_particle();
            this.object_manager.addEvent(new Event("start_instance", null, [this, association_name]));
            var send_event = new Event("set_association_name", null, [association_name]);
            this.object_manager.addEvent(new Event("narrow_cast", null, [this, association_name , send_event]));
            this.particles[this.new_particle_id] = association_name
            this.enter_Root_main_creating_behaviour_idle();
        }
        catched = true;
    }
    
    return catched;
};

Field.prototype.transition_Root_main_listening_behaviour = function(event) {
    var catched = false;
    if (!catched) {
        if (this.current_state[this.Root_main_listening_behaviour][0] === this.Root_main_listening_behaviour_listening) {
            catched = this.transition_Root_main_listening_behaviour_listening(event);
        }
    }
    return catched;
};

Field.prototype.transition_Root_main_listening_behaviour_listening = function(event) {
    var catched = false;
    var enableds = new Array();
    if (event.name === "reset" && event.port === "input") {
        enableds.push(1);
    }
    
    if (event.name === "update_time" && event.port === "input") {
        enableds.push(2);
    }
    
    if (event.name === "create_particle" && event.port === "input") {
        enableds.push(3);
    }
    
    if (event.name === "delete_particle" && event.port === "input") {
        enableds.push(4);
    }
    
    if (event.name === "key_press" && event.port === "ui") {
        var parameters = event.parameters;
        
        var key = parameters[0];
        
        var active_window = parameters[1];
        if (key == ui.KEYCODES.DELETE && active_window == this.field_window) {
            enableds.push(5);
        }
    }
    
    if (enableds.length > 1) {
        console.log("Runtime warning : indeterminism detected in a transition from node Root_main_listening_behaviour_listening. Only the first in document order enabled transition is executed.")
    }
    
    if (enableds.length > 0) {
        var enabled = enableds[0];
        if (enabled === 1) {
            this.exit_Root_main_listening_behaviour_listening();
            this.text.set_text("0.0");
            this.particles = {};
            this.object_manager.addEvent(new Event("delete_instance", null, [this, 'particles']));
            this.enter_Root_main_listening_behaviour_listening();
        }
        else if (enabled === 2) {
            var parameters = event.parameters;
            
            var new_time = parameters[0];
            this.exit_Root_main_listening_behaviour_listening();
            this.text.set_text(new_time)
            this.enter_Root_main_listening_behaviour_listening();
        }
        else if (enabled === 3) {
            var parameters = event.parameters;
            
            var params = parameters[0];
            this.exit_Root_main_listening_behaviour_listening();
            this.addEvent(new Event("create_particle", null, [params]));
            this.enter_Root_main_listening_behaviour_listening();
        }
        else if (enabled === 4) {
            var parameters = event.parameters;
            
            var particle_id = parameters[0];
            this.exit_Root_main_listening_behaviour_listening();
            this.object_manager.addEvent(new Event("delete_instance", null, [this, this.particles[particle_id]]));
            delete this.particles[particle_id]
            this.enter_Root_main_listening_behaviour_listening();
        }
        else if (enabled === 5) {
            var parameters = event.parameters;
            
            var key = parameters[0];
            
            var active_window = parameters[1];
            this.exit_Root_main_listening_behaviour_listening();
            this.controller.outputEvent(new Event("delete_selected", "output", []));
            this.enter_Root_main_listening_behaviour_listening();
        }
        catched = true;
    }
    
    return catched;
};

Field.prototype.transition_Root_stopped = function(event) {
    var catched = false;
    return catched;
};

// Execute transitions
Field.prototype.transition = function(event) {
    if (!event) event = new Event();
    this.state_changed = this.transition_Root(event);
};

// inState method for statechart
Field.prototype.inState = function(nodes) {
    for (var c in this.current_state) {
        if (!this.current_state.hasOwnProperty(c)) continue;
        var new_nodes = new Array();
        for (var n in nodes) {
            if (!nodes.hasOwnProperty(n)) continue;
            if (this.current_state[c].indexOf(nodes[n]) === -1) {
                new_nodes.push(nodes[n]);
            }
        }
        nodes = new_nodes;
        if (nodes.length === 0) {
            return true;
        }
    }
    return false;
};

Field.prototype.commonConstructor = function(controller) {
    if (!controller) controller = null;
    // Constructor part that is common for all constructors.
    RuntimeClassBase.call(this);
    
    // User defined input ports
    this.inports = new Object();
    this.controller = controller;
    this.object_manager = (controller == null ? null : controller.object_manager);
    this.current_state = new Object();
    this.history_state = new Object();
    
    // Initialize statechart
    this.current_state[this.Root] = new Array();
    this.current_state[this.Root_main] = new Array();
    this.current_state[this.Root_main_main_behaviour] = new Array();
    this.current_state[this.Root_main_creating_behaviour] = new Array();
    this.current_state[this.Root_main_listening_behaviour] = new Array();
};

Field.prototype.start = function() {
    RuntimeClassBase.prototype.start.call(this);
    this.enterDefault_Root_main();
};

// put class in global diagram object
ParticleInteraction.Field = Field;

// The actual constructor
var Particle = function(controller, canvas, particle_id, x, y, r) {
    Particle.prototype.commonConstructor.call(this,controller);
    
    // constructor body (user-defined)
    this.canvas = canvas
    this.x = x
    this.y = y
    this.r = r
    this.circle_id = this.canvas.add_circle(x, y, r, {fill:"red"})
    this.middle_id = this.canvas.add_circle(x, y, 4, {fill:"orange"})
    this.particle_id = particle_id
    ui.bind_event(this.circle_id, ui.EVENTS.MOUSE_PRESS, this.controller, 'mouse_click', this.inports['particle_ui']);
    ui.bind_event(this.circle_id, ui.EVENTS.MOUSE_RIGHT_CLICK, this.controller, 'mouse_click', this.inports['particle_ui']);
};


Particle.prototype = new RuntimeClassBase();

// Unique IDs for all statechart nodes
Particle.prototype.Root = 0;
Particle.prototype.Root_initializing = 1;
Particle.prototype.Root_running = 2;
Particle.prototype.Root_deleted = 3;

// User defined destructor
Particle.prototype.destructor = function() {
    this.canvas.remove_element(this.circle_id)
    this.canvas.remove_element(this.middle_id)
    
};
// Statechart enter/exit action method(s) :

Particle.prototype.enter_Root_initializing = function() {
    this.current_state[this.Root].push(this.Root_initializing);
};

Particle.prototype.exit_Root_initializing = function() {
    this.current_state[this.Root] = new Array();
};

Particle.prototype.enter_Root_running = function() {
    this.current_state[this.Root].push(this.Root_running);
};

Particle.prototype.exit_Root_running = function() {
    this.current_state[this.Root] = new Array();
};

Particle.prototype.enter_Root_deleted = function() {
    this.current_state[this.Root].push(this.Root_deleted);
};

Particle.prototype.exit_Root_deleted = function() {
    this.current_state[this.Root] = new Array();
};

// Statechart transitions :

Particle.prototype.transition_Root = function(event) {
    var catched = false;
    if (!catched) {
        if (this.current_state[this.Root][0] === this.Root_initializing) {
            catched = this.transition_Root_initializing(event);
        }
        else if (this.current_state[this.Root][0] === this.Root_running) {
            catched = this.transition_Root_running(event);
        }
        else if (this.current_state[this.Root][0] === this.Root_deleted) {
            catched = this.transition_Root_deleted(event);
        }
    }
    return catched;
};

Particle.prototype.transition_Root_initializing = function(event) {
    var catched = false;
    var enableds = new Array();
    if (event.name === "set_association_name") {
        enableds.push(1);
    }
    
    if (enableds.length > 1) {
        console.log("Runtime warning : indeterminism detected in a transition from node Root_initializing. Only the first in document order enabled transition is executed.")
    }
    
    if (enableds.length > 0) {
        var enabled = enableds[0];
        if (enabled === 1) {
            var parameters = event.parameters;
            
            var association_name = parameters[0];
            this.exit_Root_initializing();
            this.association_name = association_name
            this.enter_Root_running();
        }
        catched = true;
    }
    
    return catched;
};

Particle.prototype.transition_Root_running = function(event) {
    var catched = false;
    var enableds = new Array();
    if (event.name === "move_particle" && event.port === "input") {
        var parameters = event.parameters;
        
        var params = parameters[0];
        if (params[0] == this.particle_id) {
            enableds.push(1);
        }
    }
    
    if (event.name === "color_particle" && event.port === "input") {
        var parameters = event.parameters;
        
        var params = parameters[0];
        if (params[0] == this.particle_id) {
            enableds.push(2);
        }
    }
    
    if (event.name === "mouse_click" && event.port === "particle_ui") {
        var parameters = event.parameters;
        
        var x = parameters[0];
        
        var y = parameters[1];
        
        var button = parameters[2];
        if (button == ui.MOUSE_BUTTONS.LEFT) {
            enableds.push(3);
        }
    }
    
    if (event.name === "mouse_click" && event.port === "particle_ui") {
        var parameters = event.parameters;
        
        var x = parameters[0];
        
        var y = parameters[1];
        
        var button = parameters[2];
        if (button == ui.MOUSE_BUTTONS.RIGHT) {
            enableds.push(4);
        }
    }
    
    if (enableds.length > 1) {
        console.log("Runtime warning : indeterminism detected in a transition from node Root_running. Only the first in document order enabled transition is executed.")
    }
    
    if (enableds.length > 0) {
        var enabled = enableds[0];
        if (enabled === 1) {
            var parameters = event.parameters;
            
            var params = parameters[0];
            this.exit_Root_running();
            var x = params[1][0]
            var y = params[1][1]
            this.circle_id.set_position(x, y)
            this.middle_id.set_position(x, y)
            this.enter_Root_running();
        }
        else if (enabled === 2) {
            var parameters = event.parameters;
            
            var params = parameters[0];
            this.exit_Root_running();
            this.circle_id.set_color(params[1])
            this.enter_Root_running();
        }
        else if (enabled === 3) {
            var parameters = event.parameters;
            
            var x = parameters[0];
            
            var y = parameters[1];
            
            var button = parameters[2];
            this.exit_Root_running();
            this.controller.outputEvent(new Event("particle_clicked", "output", [this.particle_id]));
            this.enter_Root_running();
        }
        else if (enabled === 4) {
            var parameters = event.parameters;
            
            var x = parameters[0];
            
            var y = parameters[1];
            
            var button = parameters[2];
            this.exit_Root_running();
            this.controller.outputEvent(new Event("particle_right_clicked", "output", [this.particle_id]));
            this.enter_Root_running();
        }
        catched = true;
    }
    
    return catched;
};

Particle.prototype.transition_Root_deleted = function(event) {
    var catched = false;
    return catched;
};

// Execute transitions
Particle.prototype.transition = function(event) {
    if (!event) event = new Event();
    this.state_changed = this.transition_Root(event);
};

// inState method for statechart
Particle.prototype.inState = function(nodes) {
    for (var c in this.current_state) {
        if (!this.current_state.hasOwnProperty(c)) continue;
        var new_nodes = new Array();
        for (var n in nodes) {
            if (!nodes.hasOwnProperty(n)) continue;
            if (this.current_state[c].indexOf(nodes[n]) === -1) {
                new_nodes.push(nodes[n]);
            }
        }
        nodes = new_nodes;
        if (nodes.length === 0) {
            return true;
        }
    }
    return false;
};

Particle.prototype.commonConstructor = function(controller) {
    if (!controller) controller = null;
    // Constructor part that is common for all constructors.
    RuntimeClassBase.call(this);
    
    // User defined input ports
    this.inports = new Object();
    this.inports["particle_ui"] = controller.addInputPort("particle_ui", this);
    this.controller = controller;
    this.object_manager = (controller == null ? null : controller.object_manager);
    this.current_state = new Object();
    this.history_state = new Object();
    
    // Initialize statechart
    this.current_state[this.Root] = new Array();
};

Particle.prototype.start = function() {
    RuntimeClassBase.prototype.start.call(this);
    this.enter_Root_initializing();
};

// put class in global diagram object
ParticleInteraction.Particle = Particle;

var ObjectManager = function(controller) {
    ObjectManagerBase.call(this, controller);
};

ObjectManager.prototype = new ObjectManagerBase();

ObjectManager.prototype.instantiate = function(class_name, construct_params) {
    if (class_name === "MainApp") {
        var instance = new MainApp(this.controller, construct_params[0]);
        instance.associations = new Object();
        instance.associations["fields"] = new Association("Field", 0, -1);
    } else if (class_name === "Field") {
        var instance = new Field(this.controller, construct_params[0]);
        instance.associations = new Object();
        instance.associations["parent"] = new Association("MainApp", 1, 1);
        instance.associations["particles"] = new Association("Particle", 0, -1);
    } else if (class_name === "Particle") {
        var instance = new Particle(this.controller, construct_params[0], construct_params[1], construct_params[2], construct_params[3], construct_params[4]);
        instance.associations = new Object();
        instance.associations["parent"] = new Association("Field", 1, 1);
    }
    return instance;
};

// put in global diagram object
ParticleInteraction.ObjectManager = ObjectManager;

var Controller = function(resolution, keep_running, finished_callback) {
    if (keep_running === undefined) keep_running = true;
    JsEventLoopControllerBase.call(this, new ObjectManager(this), keep_running, finished_callback);
    this.addInputPort("ui");
    this.addInputPort("input");
    this.object_manager.createInstance("MainApp", [resolution]);
};

Controller.prototype = new JsEventLoopControllerBase();

// put in global diagram object
ParticleInteraction.Controller = Controller;

})();
