
 /**
  * @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;
    }

}

