/**
 * @file
 * @ingroup <<<GROUP>>>
 * @brief   The internals for <<<STATEMACHINENAME>>>. As a user this should be ignored.
 * @detail  <<<BRIEF>>>
 *
 *          This statemachine has the following transition table:
 *
 *          <<<TTT_BOOST_SML>>>
 *
 *          This code is Autogenerated from '<<<PYIFGENNAME>>>' with the MIT License.
 *          As such, please only hand-code within 'USER' tags.
 *
 * @author  <<<AUTHOR>>>
 */
#define SM_THREAD_<<<StateMachineThread=1>>>
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

namespace <<<NAMESPACE>>>
{
    /// <summary>
    /// Internal dispatchable interface for event structs for <<<STATEMACHINENAME>>>.
    /// </summary>
    internal interface IDispatchable {
        void Dispatch(<<<STATEMACHINENAME>>>StateMachine sm, I<<<STATEMACHINENAME>>>Context controller);
    }

    /// <summary>
    /// E<<<STATEMACHINENAME>>>State internal enumeration.
    /// </summary>
    internal enum E<<<STATEMACHINENAME>>>State : ushort                                                                                                      
    {
    <<<PER_STATE_BEGIN>>>
        <<<STATENAME>>>,
    <<<PER_STATE_END>>>
    };
    /// <summary>
    /// <<<STATEMACHINENAME>>>State internal base class.
    /// </summary>
    internal class <<<STATEMACHINENAME>>>State
    {
        <<<PER_EVENT_BEGIN>>>
        internal virtual void Trigger<<<EVENTNAME>>>(I<<<STATEMACHINENAME>>>Context context, <<<STATEMACHINENAME>>>StateMachine sm, <<<EVENTNAME>>> data){}
        <<<PER_EVENT_END>>>
        internal virtual void OnEntry(I<<<STATEMACHINENAME>>>Context context){}
        internal virtual void OnExit(I<<<STATEMACHINENAME>>>Context context){}
    };
    <<<PER_STATETRANSITION_BEGIN>>>
    /// <summary>
    /// <<<STATENAME>>> specific internal implementation.
    /// </summary>
    internal class <<<STATENAME>>> : <<<STATEMACHINENAME>>>State
    {
        <<<PER_EVENTTRANSITION_BEGIN>>>
        internal override void Trigger<<<EVENTNAME>>>(I<<<STATEMACHINENAME>>>Context context, <<<STATEMACHINENAME>>>StateMachine sm, <<<EVENTNAME>>> data)
        {
            <<<PER_GUARDTRANSITION_BEGIN>>>
            if (context.<<<GUARDNAME>>>())
            {
                sm.Exit<<<<STATENAMEIFNEXTSTATE>>>>();
                context.<<<ACTIONNAME>>>(data);
                sm.Enter<<<<NEXTSTATENAME>>>>();
                sm.estate = E<<<STATEMACHINENAME>>>State.<<<NEXTSTATENAME>>>;
                return;
            }
            <<<PER_GUARDTRANSITION_END>>>
        }
        <<<PER_EVENTTRANSITION_END>>>
        internal override void OnEntry(I<<<STATEMACHINENAME>>>Context context)
        {
            context.On<<<STATENAME>>>Entry();
        }
        internal override void OnExit(I<<<STATEMACHINENAME>>>Context context)
        {
            context.On<<<STATENAME>>>Exit();
        }
    };
    <<<PER_STATETRANSITION_END>>>

    /// Implementation of Dispatchable's.
    <<<PER_EVENT_BEGIN>>>
    public partial class <<<EVENTNAME>>> : IDispatchable {
        void IDispatchable.Dispatch(<<<STATEMACHINENAME>>>StateMachine sm, I<<<STATEMACHINENAME>>>Context controller)
        {
            sm.state.Trigger<<<EVENTNAME>>>(controller, sm, this);
        }
    };
    <<<PER_EVENT_END>>>

    /// <summary>
    /// <<<STATEMACHINENAME>>>StateMachine public implementation.
    /// </summary>
    public partial class <<<STATEMACHINENAME>>>StateMachine
    {
        internal void Reset()
        {
            Enter<<<<STATE_0>>>>();
            estate = E<<<STATEMACHINENAME>>>State.<<<STATE_0>>>;
        }
#if SM_THREAD_1
        internal ConcurrentQueue<IDispatchable> dispatchQ = new ();
        // An action to consume the ConcurrentQueue.
        //System.Action dispatchAction;
        internal Thread dispatchThread;
        internal void Dispatch()
        {
            while(true)
            {
                if (dispatchQ.TryDequeue(out IDispatchable next))
                {
                    next.Dispatch(this, controller);
                }
                Thread.Sleep(1);
            }
        }
#endif
        internal void Enter<StateT>() where StateT : new()
        {
            state = new StateT() as <<<STATEMACHINENAME>>>State;
            state.OnEntry(controller);
        }
        internal void Exit<StateT>()
        {
            state.OnExit(controller);
        }
        internal I<<<STATEMACHINENAME>>>Context controller;
        internal E<<<STATEMACHINENAME>>>State estate;
        internal <<<STATEMACHINENAME>>>State state;
    };
} // namespace <<<NAMESPACE>>>

