
/**
 * @param {String} the name of this state
 **/
function State(name) {

    this.ERROR_NAME = "STATE_TRANSITION_ERROR"
    this.name = name;
    
    var selfAllowed = true; // indicates that all states are allowed to go to themselves per default
    this.setSelfActivationAllowed = function(isGoToItselfAllowed) {
        selfAllowed = isGoToItselfAllowed;
    }
    
    this.allowedNextStates = new Array();
    
    /**
     * @param {String[]} arrayOfStateNames indicating allowed states to go to from this state
     **/
    this.setAllowedFollowing = function(arrayOfStateNames) {
        this.allowedNextStates = arrayOfStateNames;
    }
    
    this.setActivationBehaviour = function(func) {
        if (func instanceof Function) {
            this._activate = func;
        }
        else {
            throw new Error("parameter of setActivationBehaviour() was no Function, was:" + func);
        }
    }
    
    this.goTo = function(state) {
    
        if (state instanceof State) {
            if (state == this && selfAllowed) {
                this._activate();
                return this;
            }
            if (this.isAllowedNextState(state.name)) {
                state._activate();
                return state;
            }
            else {
                var e = new Error(this.ERROR_NAME + " - It is not allowed to go\nfrom state:" + this.name + " to state:" + state.name);
                e.name = this.ERROR_NAME;
                throw e;
                return null;
            }
        }
        else {
            throw new Error("Parameter of goToState() was no State");
            return null;
        }
    }
    
    this.isAllowedNextState = function(stateName) {
    
        if (selfAllowed && this.name == stateName) {
            return true;
        }
        
        for (var i = 0; i < this.allowedNextStates.length; i++) {
            var str = this.allowedNextStates[i];
            if (typeof str != "undefined" && str != null && str == stateName) {
                return true;
            }
        }
        return false;
    }
    
    this.getName = function() {
        return this.name;
    }
    
    defaultActivation = function() {
        alert("This is states " + this.name + " DEFAULT activation function! Give this state its own behaviour with: setActivationBehaviour(yourFunction) on this state.");
    }
    // overide default behaviour
    this._activate = defaultActivation;
    
}


function StateAutomaton() {

    this.currentState;
    this.lastStateName;
    this.states = {};
    
    var me = this;
    
    this.addState = function(state) {
        this.states[state.name] = state;
    }
    
    this.setStartState = function(state) {
        this.lastStateName = state.name;
        this.currentState = state;
    }
    
    this.goToState = function(state) {
    
        if (this.currentState.isAllowedNextState(state.name)) {
            var newState = this.currentState.goTo(state);
            this.lastStateName = this.currentState.name;
            this.currentState = newState;
        }
        else {
            alert("It is not allowed to change from " + this.currentState.name + " to " + state.name);
        }
        return this.currentState;
    }
    
    this.goToStateByName = function(stateName) {
        return this.goToState(this.states[stateName]);
    }
    
    this.getCurrentState = function() {
        return this.currentState;
    }
    
    this.getLastState = function() {
        return this.states[this.lastStateName];
    }
    
    this.toString = function() {
        var str = "StateAutomaton:";
        str += "\n\tcurrent state: " + this.getCurrentState().name;
        str += "\n\tlast visited state: " + this.getLastState().name;
        return str;
    }
    
}


