using AyaNova.Biz;
namespace AyaNova.Api.ControllerHelpers
{




    /// <summary>
    /// Contains the current status of the server
    /// is injected everywhere for routes and others to check
    /// </summary>
    public class ApiServerState
    {

        //private ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger<ApiServerState>();
        public enum ServerState
        {
            ///<summary>Unknown state, used for parsing</summary>
            UNKNOWN = 0,
            ///<summary>No access for anyone API completely locked down. Not set by user but rather by internal server operations like importing or backup.</summary>
            Closed = 1,
            ///<summary>Access only to API Operations routes. Can be set by Ops user</summary>
            OpsOnly = 2,
            ///<summary>Open for all users (default). Can be set by Ops user</summary>
            Open = 3
        }

        private ServerState _currentState = ServerState.Closed;
        private ServerState _priorState = ServerState.Closed;
        private string _reason = string.Empty;
        private string _priorReason = string.Empty;
        private bool SYSTEM_LOCK = false;//really this is a license lock but not called that 

        public ApiServerState()
        {

        }



        internal void SetSystemLock(string reason)
        {
            //Lock down the server for license related issue
            //Only SuperUser account (id=1) can login or do anything, treats as if server was set to closed even if they change it to open
            //only way to reset it is to fetch a valid license
            //
            var msg = $"{reason}\r\nLogin as SuperUser to start evaluation / install license";
            SetState(ServerState.OpsOnly, msg);
            SYSTEM_LOCK = true;
        }


        //WARNING: if in future this is used for anything other than a license then it will need to see if locked for another reason before unlocking
        //recommend putting a code number in the reason then looking to see if it has the matching code 
        internal void ClearSystemLock()
        {
            SYSTEM_LOCK = false;
            SetState(ServerState.Open, "");
        }

        /// <summary>
        /// Set the server state
        /// </summary>
        /// <param name="newState"></param>
        /// <param name="reason"></param>
        public void SetState(ServerState newState, string reason)
        {
            //No changes allowed during a system lock
            if (SYSTEM_LOCK) return;

            _reason = reason;//keep the reason even if the state doesn't change
            if (newState == _currentState) return;

            //Here we will likely need to trigger a notification to users if the state is going to be shutting down or is shut down
            _priorState = _currentState;//keep the prior state so it can be resumed easily
            _priorReason = _reason;//keep the original reason

            _currentState = newState;
        }

        /// <summary>
        /// Get the current state of the server
        /// </summary>
        /// <returns></returns>
        public ServerState GetState()
        {
            return _currentState;
        }

        /// <summary>
        /// Get the current reason for the state of the server
        /// </summary>
        /// <returns></returns>
        public string Reason
        {
            get
            {
                if (_currentState == ServerState.Open)
                {
                    return "";
                }
                else
                {
                    return $"\"{_reason}\"";
                    // if (_currentState == ServerState.Closed)
                    //     return $"{ AyaNova.Biz.TranslationBiz.GetDefaultTranslationAsync("ErrorAPI2000").Result}\r\n{_reason}";
                    // else //opsonly
                    //     return $"{ AyaNova.Biz.TranslationBiz.GetDefaultTranslationAsync("ErrorAPI2001").Result}\r\n{_reason}";
                }
            }
        }

        //get the api error code associated with the server state
        public ApiErrorCode ApiErrorCode
        {
            get
            {
                switch (_currentState)
                {
                    case ServerState.Open:
                        throw new System.NotSupportedException("ApiServerState:ApiErrorCode - No error code is associated with server state OPEN");
                    case ServerState.OpsOnly:
                        return ApiErrorCode.API_OPS_ONLY;
                    case ServerState.Closed:
                        return ApiErrorCode.API_CLOSED;

                }
                throw new System.NotSupportedException("ApiServerState:ApiErrorCode - No error code is associated with server state UNKNOWN");
            }

        }


        public void SetOpsOnly(string reason)
        {
            //No changes allowed during a system lock
            if (SYSTEM_LOCK) return;
            SetState(ServerState.OpsOnly, reason);
        }


        public void SetClosed(string reason)
        {
            //No changes allowed during a system lock
            if (SYSTEM_LOCK) return;
            SetState(ServerState.Closed, reason);
        }

        public void SetOpen()
        {
            //No changes allowed during a system lock
            if (SYSTEM_LOCK) return;
            SetState(ServerState.Open, string.Empty);
        }

        public void ResumePriorState()
        {
            //No changes allowed during a system lock
            if (SYSTEM_LOCK) return;
            SetState(_priorState, _priorReason);
        }


        public bool IsOpsOnly
        {
            get
            {
                return _currentState == ServerState.OpsOnly && !SYSTEM_LOCK;
            }
        }

        public bool IsOpen
        {
            get
            {
                return _currentState == ServerState.Open && !SYSTEM_LOCK;
            }
        }


        public bool IsClosed
        {
            get
            {
                return _currentState == ServerState.Closed || SYSTEM_LOCK;
            }
        }

        public bool IsOpenOrOpsOnly
        {
            get
            {
                return (IsOpen || IsOpsOnly) && !SYSTEM_LOCK;
            }
        }

        public bool IsSystemLocked
        {
            get
            {
                return SYSTEM_LOCK;
            }
        }




    }//eoc


}//eons