<commit_before>﻿using NWheels.Injection;
using NWheels.Orchestration;
using System;
using System.Collections.Generic;
using System.Threading;

namespace NWheels.Microservices
{
    public class MicroserviceHost
    {
        private readonly BootConfiguration _bootConfig;
        private readonly List<ILifecycleListenerComponent> _lifecycleComponents;
        private readonly RevertableSequence _configureSequence;
        private readonly RevertableSequence _loadSequence;
        private readonly RevertableSequence _activateSequence;
        private int _initializationCount = 0;
        private IContainer _container;
        private IMicroserviceHostLogger _logger;        
        private TransientStateMachine<MicroserviceState, MicroserviceTrigger> _stateMachine;        

        //-----------------------------------------------------------------------------------------------------------------------------------------------------

        public MicroserviceHost(BootConfiguration bootConfig)
        {
            _bootConfig = bootConfig;
            _configureSequence = new RevertableSequence(new ConfigureSequenceCodeBehind(this));
            _loadSequence = new RevertableSequence(new LoadSequenceCodeBehind(this));
            _activateSequence = new RevertableSequence(new ActivateSequenceCodeBehind(this));
            _lifecycleComponents = new List<ILifecycleListenerComponent>();
        }

        //-----------------------------------------------------------------------------------------------------------------------------------------------------

        public event EventHandler StateChanged;

        //-----------------------------------------------------------------------------------------------------------------------------------------------------

        public void Configure()
        {
            InitializeBeforeConfigure();

            using (_logger.NodeLoading())
            {
                try
                {
                    _stateMachine.ReceiveTrigger(MicroserviceTrigger.Configure);
                }
                catch (Exception e)
                {
                    _logger.NodeHasFailedToConfigure(e);
                    throw;
                }

                if (_stateMachine.CurrentState != MicroserviceState.Configured)
                {
                    throw _logger.NodeHasFailedToConfigure();
                }
            }
        }

        //-----------------------------------------------------------------------------------------------------------------------------------------------------

        public void Load()
        {
            using (_logger.NodeLoading())
            {
                try
                {
                    _stateMachine.ReceiveTrigger(MicroserviceTrigger.Load);
                }
                catch (Exception e)
                {
                    _logger.NodeHasFailedToLoad(e);
                    throw;
                }

                if (_stateMachine.CurrentState != MicroserviceState.Standby)
                {
                    throw _logger.NodeHasFailedToLoad();
                }

                _logger.NodeSuccessfullyLoaded();
            }
        }

        //-----------------------------------------------------------------------------------------------------------------------------------------------------

        public void Activate()
        {
            using (_logger.NodeActivating())
            {
                try
                {
                    _stateMachine.ReceiveTrigger(MicroserviceTrigger.Activate);
                }
                catch (Exception e)
                {
                    _logger.NodeHasFailedToActivate(e);
                    throw;
                }

                if (_stateMachine.CurrentState != MicroserviceState.Active)
                {
                    throw _logger.NodeHasFailedToActivate();
                }

                _logger.NodeSuccessfullyActivated();
            }
        }

        //-----------------------------------------------------------------------------------------------------------------------------------------------------

        public void LoadAndActivate()
        {
            InitializeBeforeConfigure();

            using (_logger.NodeStartingUp(
                /*_bootConfig.ApplicationName,
                _bootConfig.EnvironmentType,
                _bootConfig.EnvironmentName,
                _bootConfig.NodeName,
                _bootConfig.InstanceId*/))
            {
                Load();
                Activate();
            }
        }

        //-----------------------------------------------------------------------------------------------------------------------------------------------------

        public void Deactivate()
        {
            using (_logger.NodeDeactivating())
            {
                _stateMachine.ReceiveTrigger(MicroserviceTrigger.Deactivate);

                if (_stateMachine.CurrentState != MicroserviceState.Standby)
                {
                    throw _logger.NodeHasFailedToDeactivate();
                }

                _logger.NodeDeactivated();
            }
        }

        //-----------------------------------------------------------------------------------------------------------------------------------------------------

        public void DeactivateAndUnload()
        {
            using (_logger.NodeShuttingDown())
            {
                if (_stateMachine.CurrentState == MicroserviceState.Active)
                {
                    Deactivate();
                }

                if (_stateMachine.CurrentState == MicroserviceState.Standby)
                {
                    Unload();
                }
            }
        }

        //-----------------------------------------------------------------------------------------------------------------------------------------------------

        public void Unload()
        {
            using (_logger.NodeUnloading())
            {
                _stateMachine.ReceiveTrigger(MicroserviceTrigger.Unload);

                if (_stateMachine.CurrentState != MicroserviceState.Down)
                {
                    throw _logger.NodeHasFailedToUnload();
                }

                _logger.NodeUnloaded();
            }

            FinalizeAfterUnload();
        }

        //-------------------------------------------------------------------------------------------------------------------------------------------------

        private bool ExecuteConfigurePhase()
        {
            return ExecutePhase(_configureSequence.Perform, _logger.NodeConfigureError);
        }

        //-------------------------------------------------------------------------------------------------------------------------------------------------

        private bool ExecuteLoadPhase()
        {
            return ExecutePhase(_loadSequence.Perform, _logger.NodeLoadError);
        }

        //-------------------------------------------------------------------------------------------------------------------------------------------------

        private bool ExecuteActivatePhase()
        {
            return ExecutePhase(_activateSequence.Perform, _logger.NodeActivationError);
        }

        //-------------------------------------------------------------------------------------------------------------------------------------------------

        private bool ExecuteDeactivatePhase()<commit_msg>Logger property added to MicroserviceHost;<commit_after>﻿using NWheels.Injection;
using NWheels.Orchestration;
using System;
using System.Collections.Generic;
using System.Threading;

namespace NWheels.Microservices
{
    public class MicroserviceHost
    {
        private readonly BootConfiguration _bootConfig;
        private readonly List<ILifecycleListenerComponent> _lifecycleComponents;
        private readonly RevertableSequence _configureSequence;
        private readonly RevertableSequence _loadSequence;
        private readonly RevertableSequence _activateSequence;
        private int _initializationCount = 0;
        private IContainer _container;
        private IMicroserviceHostLogger _logger;        
        private TransientStateMachine<MicroserviceState, MicroserviceTrigger> _stateMachine;        

        //-----------------------------------------------------------------------------------------------------------------------------------------------------

        public MicroserviceHost(BootConfiguration bootConfig)
        {
            _bootConfig = bootConfig;
            _configureSequence = new RevertableSequence(new ConfigureSequenceCodeBehind(this));
            _loadSequence = new RevertableSequence(new LoadSequenceCodeBehind(this));
            _activateSequence = new RevertableSequence(new ActivateSequenceCodeBehind(this));
            _lifecycleComponents = new List<ILifecycleListenerComponent>();
        }
        
        //-----------------------------------------------------------------------------------------------------------------------------------------------------

        public event EventHandler StateChanged;

        //-----------------------------------------------------------------------------------------------------------------------------------------------------

        public void Configure()
        {
            InitializeBeforeConfigure();

            using (_logger.NodeLoading())
            {
                try
                {
                    _stateMachine.ReceiveTrigger(MicroserviceTrigger.Configure);
                }
                catch (Exception e)
                {
                    _logger.NodeHasFailedToConfigure(e);
                    throw;
                }

                if (_stateMachine.CurrentState != MicroserviceState.Configured)
                {
                    throw _logger.NodeHasFailedToConfigure();
                }
            }
        }

        //-----------------------------------------------------------------------------------------------------------------------------------------------------

        public void Load()
        {
            using (_logger.NodeLoading())
            {
                try
                {
                    _stateMachine.ReceiveTrigger(MicroserviceTrigger.Load);
                }
                catch (Exception e)
                {
                    _logger.NodeHasFailedToLoad(e);
                    throw;
                }

                if (_stateMachine.CurrentState != MicroserviceState.Standby)
                {
                    throw _logger.NodeHasFailedToLoad();
                }

                _logger.NodeSuccessfullyLoaded();
            }
        }

        //-----------------------------------------------------------------------------------------------------------------------------------------------------

        public void Activate()
        {
            using (_logger.NodeActivating())
            {
                try
                {
                    _stateMachine.ReceiveTrigger(MicroserviceTrigger.Activate);
                }
                catch (Exception e)
                {
                    _logger.NodeHasFailedToActivate(e);
                    throw;
                }

                if (_stateMachine.CurrentState != MicroserviceState.Active)
                {
                    throw _logger.NodeHasFailedToActivate();
                }

                _logger.NodeSuccessfullyActivated();
            }
        }

        //-----------------------------------------------------------------------------------------------------------------------------------------------------

        public void LoadAndActivate()
        {
            InitializeBeforeConfigure();

            using (_logger.NodeStartingUp(
                /*_bootConfig.ApplicationName,
                _bootConfig.EnvironmentType,
                _bootConfig.EnvironmentName,
                _bootConfig.NodeName,
                _bootConfig.InstanceId*/))
            {
                Load();
                Activate();
            }
        }

        //-----------------------------------------------------------------------------------------------------------------------------------------------------

        public void Deactivate()
        {
            using (_logger.NodeDeactivating())
            {
                _stateMachine.ReceiveTrigger(MicroserviceTrigger.Deactivate);

                if (_stateMachine.CurrentState != MicroserviceState.Standby)
                {
                    throw _logger.NodeHasFailedToDeactivate();
                }

                _logger.NodeDeactivated();
            }
        }

        //-----------------------------------------------------------------------------------------------------------------------------------------------------

        public void DeactivateAndUnload()
        {
            using (_logger.NodeShuttingDown())
            {
                if (_stateMachine.CurrentState == MicroserviceState.Active)
                {
                    Deactivate();
                }

                if (_stateMachine.CurrentState == MicroserviceState.Standby)
                {
                    Unload();
                }
            }
        }

        //-----------------------------------------------------------------------------------------------------------------------------------------------------

        public void Unload()
        {
            using (_logger.NodeUnloading())
            {
                _stateMachine.ReceiveTrigger(MicroserviceTrigger.Unload);

                if (_stateMachine.CurrentState != MicroserviceState.Down)
                {
                    throw _logger.NodeHasFailedToUnload();
                }

                _logger.NodeUnloaded();
            }

            FinalizeAfterUnload();
        }

        //-------------------------------------------------------------------------------------------------------------------------------------------------

        public IMicroserviceHostLogger Logger
        {
            get
            {
                return _logger;
            }
        }
        
        //-------------------------------------------------------------------------------------------------------------------------------------------------

        private bool ExecuteConfigurePhase()
        {
            return ExecutePhase(_configureSequence.Perform, _logger.NodeConfigureError);
        }

        //-------------------------------------------------------------------------------------------------------------------------------------------------

        private bool ExecuteLoadPhase()
        {
            return ExecutePhase(_loadSequence.Perform, _logger.NodeLoadError);
        }

        //-------------------------------------------------------------------------------------------------------------------------------------------------

        private bool ExecuteActivatePhase()
        {
            return ExecutePhase(_activateSequence.Perform, _logger.NodeActivationError);
        }

        //-------------------------------------------------------------------------------------------------------------------------------------------------

        private bool ExecuteDeactivatePhase()
{'fraction_non_alphanumeric': 0.30876532796989553, 'fraction_numerical': 0.0001297605917082982, 'mean_word_length': 0.71820309887415, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5155767', 'n_tokens_mistral': 2739, 'n_tokens_neox': 2498, 'n_words': 407}