public RunnableVm(ISender <IRingCommand> sender, Action <string> writeLog, RunnableInfo model)
        {
            var logger = writeLog;

            _fsm.OnUnhandledTrigger((s, t) => writeLog($"Trigger '{t}' is not configured for state {s}"));
            _fsm.OnTransitioned(t => logger($"{UniqueId}: {t.Source} -> {t.Trigger} -> {t.Destination}"));

            _fsm.Configure(S.Zero)
            .OnActivate(() => _status.Off())
            .OnEntryFrom(T.Destroyed, () => _status.Off())
            .OnEntryFrom(T.DebugStop, Include)
            .OnEntryFrom(T.BuildStop, Include)
            .InternalTransition(T.Action, Include)
            .Permit(T.Initiated, S.Initiated)
            .Ignore(T.Stopped)
            .Ignore(T.Destroyed)
            .Ignore(T.DebugStart)
            .Ignore(T.DebugStop)
            .Ignore(T.BuildStart)
            .Ignore(T.BuildStop);

            _fsm.Configure(S.Initiated)
            .SubstateOf(S.Active)
            .OnEntryFrom(T.Initiated, () => _status.Initiated())
            .InternalTransition(T.Action, Exclude)
            .Permit(T.Started, S.Started);

            _fsm.Configure(S.Started)
            .SubstateOf(S.Active)
            .OnEntryFrom(T.Started, () => _status.Started())
            .InternalTransition(T.Action, Exclude)
            .Permit(T.HealthCheckPending, S.HealthCheck)
            .Permit(T.HealthCheckDead, S.Dead)
            .Permit(T.HealthCheckHealthy, S.Healthy)
            .Permit(T.Stopped, S.Stopped);

            _fsm.Configure(S.HealthCheck)
            .SubstateOf(S.Active)
            .OnEntryFrom(T.HealthCheckPending, () => _status.HealthCheck())
            .InternalTransition(T.Action, Exclude)
            .Ignore(T.HealthCheckPending)
            .Permit(T.Stopped, S.Stopped)
            .Permit(T.HealthCheckHealthy, S.Healthy)
            .Permit(T.HealthCheckDead, S.Dead)
            .Permit(T.Recovering, S.Recovering);

            _fsm.Configure(S.Healthy)
            .SubstateOf(S.Active)
            .OnEntryFrom(T.HealthCheckHealthy, () => _status.Healthy())
            .InternalTransition(T.Action, Exclude)
            .Permit(T.HealthCheckPending, S.HealthCheck)
            .PermitReentry(T.HealthCheckHealthy)
            .Permit(T.Stopped, S.Stopped);

            _fsm.Configure(S.Dead)
            .OnEntryFrom(T.HealthCheckDead, () => _status.Dead())
            .InternalTransition(T.Action, Restart)
            .Ignore(T.HealthCheckDead)
            .Permit(T.Stopped, S.Stopped);

            _fsm.Configure(S.Stopped)
            .OnEntryFrom(T.Stopped, () => _status.Stopped())
            .InternalTransition(T.Action, Include)
            .Permit(T.Destroyed, S.Zero)
            .Permit(T.Started, S.Started)
            .Permit(T.Initiated, S.Initiated);

            _fsm.Configure(S.Recovering)
            .SubstateOf(S.Active)
            .OnEntryFrom(T.Recovering, () => _status.Recovering())
            .InternalTransition(T.Action, Exclude)
            .Permit(T.Stopped, S.Stopped);

            _fsm.Configure(S.Debugging)
            .InternalTransition(T.Stopped, () => _status.Debugging())
            .Ignore(T.Destroyed)
            .OnEntryFrom(T.DebugStart, Exclude)
            .Permit(T.DebugStop, S.Zero);

            _fsm.Configure(S.Building)
            .InternalTransition(T.Stopped, () => _status.Building())
            .Ignore(T.Destroyed)
            .OnEntryFrom(T.BuildStart, Exclude)
            .Permit(T.BuildStop, S.Zero);

            _fsm.Configure(S.Active)
            .Permit(T.DebugStart, S.Debugging)
            .Permit(T.BuildStart, S.Building);

            _fsm.Activate();

            ModelRef = model;


            switch (model.State)
            {
            case RunnableState.ZERO:
                break;

            case RunnableState.INITIATED:
                Initiated();
                break;

            case RunnableState.STARTED:
                Initiated();
                Started();
                break;

            case RunnableState.HEALTH_CHECK:
                Initiated();
                Started();
                HealthCheck();
                break;

            case RunnableState.HEALTHY:
                Initiated();
                Started();
                Healthy();
                break;

            case RunnableState.DEAD:
                Initiated();
                Started();
                Dead();
                break;

            case RunnableState.RECOVERING:
                Initiated();
                Started();
                Recovering();
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            void Restart()
            {
                Exclude();
                Include();
            }

            void Exclude()
            {
                sender.Exclude(this);
                _status.Pending();
            }

            void Include()
            {
                sender.Include(this);
                _status.Pending();
            }
        }