using System;
using System.Collections.Generic;
using System.Threading;
using System.Diagnostics;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.Log;
using CyberX8_Core;
using System.Reflection;
using DocumentFormat.OpenXml.Wordprocessing;
namespace Aitex.Core.RT.Fsm
{
public class Entity
{
protected Thread thread = null;
protected IStateMachine fsm = null;
public bool Running { get; protected set;}
///
/// 剩余时长ToReady
///
public virtual int TimeToReady
{
get { return int.MaxValue / 2; }
}
public Entity()
{
}
public bool Initialize()
{
Init();
if (fsm != null)
{
fsm.Start();
thread = new Thread(new ThreadStart(fsm.Loop));
thread.Name = fsm.Name;
thread.Start();
LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"Create Entity Thread {fsm.Name}");
while (!thread.IsAlive)
Thread.Sleep(1);
}
return true;
}
public void Terminate()
{
if (fsm != null)
{
fsm.Stop();
}
Term();
if (thread!=null&&thread.IsAlive)
{
Thread.Sleep(100);
if (thread.IsAlive)
{
try
{
thread.Abort();
}
catch (Exception ex)
{
LOG.WriteExeption(String.Format("Entity terminate has exception."), ex);
}
}
}
//Term();
}
protected virtual bool Init()
{
return true;
}
protected virtual void Term()
{
}
protected void Transition(T state, V msg, FsmFunc func, T next)
{
Debug.Assert(typeof(T).IsEnum && typeof(V).IsEnum);
int _state = Convert.ToInt32(state);
int _next = Convert.ToInt32(next);
int _msg = Convert.ToInt32(msg);
Transition(_state, _msg, func, _next);
}
protected void Transition(T state,V msg,FsmFunc func,FsmFunc waitFunc,T next)
{
Debug.Assert(typeof(T).IsEnum && typeof(V).IsEnum);
int _state = Convert.ToInt32(state);
int _next = Convert.ToInt32(next);
int _msg = Convert.ToInt32(msg);
Transition(_state, _msg, func,waitFunc, _next);
}
protected void Transition(int state, int msg, FsmFunc func, int next)
{
if (fsm != null)
fsm.Transition(state, msg, func, next);
}
protected void Transition(int state, int msg, FsmFunc func,FsmFunc waitFunc, int next)
{
if (fsm != null)
fsm.Transition(state, msg, func,waitFunc, next);
}
protected void AnyStateTransition(int msg, FsmFunc func, int next)
{
if (fsm != null)
fsm.AnyStateTransition(msg, func, next);
}
//protected void AnyStateTransition(int msg, FsmFunc func, int next, FsmFunc monitorFunc)
//{
// if (fsm != null)
// fsm.AnyStateTransition(msg, func, next,monitorFunc);
//}
protected void AnyStateTransition(V msg, FsmFunc func, T next)
{
Debug.Assert(typeof(T).IsEnum && typeof(V).IsEnum);
int _next = Convert.ToInt32(next);
int _msg = Convert.ToInt32(msg);
AnyStateTransition(_msg, func, _next);
}
protected void AnyStateTransition(V msg, FsmFunc func, T next, FsmFunc monitorFunc)
{
Debug.Assert(typeof(T).IsEnum && typeof(V).IsEnum);
int _next = Convert.ToInt32(next);
int _msg = Convert.ToInt32(msg);
AnyStateTransition(_msg, func, _next, monitorFunc);
}
protected void EnterExitTransition(T state, FsmFunc enter, Nullable msg, FsmFunc exit) where V : struct
{
Debug.Assert(typeof(T).IsEnum && ((msg == null) || typeof(V).IsEnum));
int _state = Convert.ToInt32(state);
int _msg = msg == null ? (int)FSM_MSG.NONE : Convert.ToInt32(msg);
EnterExitTransition(_state, enter, _msg, exit);
}
protected void EnterExitTransition(int state, FsmFunc enter, int msg, FsmFunc exit)
{
if (fsm != null)
fsm.EnterExitTransition(state, enter, msg, exit);
}
public void PostMsg(T msg, params object[] args) where T : struct
{
Debug.Assert(typeof(T).IsEnum);
int id = Convert.ToInt32(msg);
PostMsg(id, args);
}
public void PostMsg(int msg, params object[] args)
{
if (fsm == null)
{
//LOG.Error($"fsm is null, post msg {msg}");
return;
}
fsm.PostMsg(msg, args);
}
public bool CheckToPostMessage(eEvent eEvent,string moduleName,int msg, params object[] args)
{
string state = Enum.GetName(typeof(T), fsm.State);
string strMsg = Enum.GetName(typeof(V), msg);
if (!fsm.FindTransition(fsm.State, msg))
{
LOG.WriteLog(eEvent, moduleName, $"{moduleName} is in {state} state,can not do {strMsg}");
return false;
}
Running = true;
fsm.PostMsg(msg, args);
LOG.WriteLog(eEvent.EV_FSM_NOTIFY, moduleName, $"{moduleName} is in {state} state,do {strMsg}");
return true;
}
public bool NullFunc(object[] param)
{
return true;
}
}
}