﻿using UnityEngine;
using System.Collections.Generic;

public class StateMachine<T>{
	private T Owner;

	private FSMState<T> CurrentState;
	private FSMState<T>	PreviousState;
	private FSMState<T> GlobalState;

	private Dictionary<string,FSMState<T>> stateRef;

	public StateMachine(){}
	public StateMachine(T Owner){
		this.Owner = Owner;
		stateRef=new Dictionary<string,FSMState<T>>();
	}

	public void Update(){
		if (GlobalState != null)
			GlobalState.OnUpdate ();
		if (CurrentState != null)
			CurrentState.OnUpdate ();
	}

	public void RevertToPreviousState(){
		if(PreviousState!=null){
				
		}
	}

	public string GetPreviousStateName(){
		if (PreviousState != null)
			return PreviousState.GetStateName ();
		return null;
	}

	protected void ChangeState(FSMState<T> newState){
		if(newState==null){
			Debug.LogError("ChangeState name not found!");
			return;
		}

		string newStateName = newState.GetStateName();
		if(CurrentState!=null && CurrentState.GetStateName()==newStateName){
			Debug.LogError("ChangeState stateName is same,statename is :"+newStateName+"\t the Owner is :"+this.Owner);
			return;
		}

		PreviousState = CurrentState;
		if(CurrentState!=null){
			CurrentState.OnExit();
		}

		CurrentState = newState;
		if(CurrentState!=null){
			CurrentState.OnEnter();
		}

	}

	public void ChangeState(string newStateName){
		if(!stateRef.ContainsKey(newStateName)){
			Debug.LogError("ChangeState name not found! name is :"+newStateName);
			return;
		}

		FSMState<T> newState=stateRef[newStateName];
		if(newState==null){
			Debug.LogError("ChangeState name not found! name is :"+newStateName);
			return;
		}

		ChangeState (newState);
	}

	public bool RegisterState(string stateName,FSMState<T> state){
		if(stateRef.ContainsKey(stateName)){
			Debug.LogError("FSMState<T> Register failed,Duplicate register");
			return false;
		}

		stateRef.Add (stateName,state);
		state.RegisterOwner (Owner);
		state.SetStateName (stateName);

		return true;
	}

	public bool RegisterGlobalState(FSMState<T> state){
		GlobalState = state;
		GlobalState.RegisterOwner (Owner);
		GlobalState.OnEnter ();
		return true;
	}

	public FSMState<T> GetCurrentState(){
		return CurrentState;
	}
	
	public bool HandleMessage(Message msg){
		if(CurrentState!=null && CurrentState.OnMessage(msg)){
			return true;
		}

		if(GlobalState!=null && GlobalState.OnMessage(msg)){
			return true;
		}
		return false;
	}
	
}
