using Hcs.Client.Internal;
using System;
using System.Linq;

namespace Hcs.Client.Api.Request.Exception
{
    internal class RemoteException : System.Exception
    {
        internal const string NO_OBJECTS_FOR_EXPORT = "INT002012";
        internal const string MISSING_IN_REGISTRY = "INT002000";
        internal const string ACCESS_DENIED = "AUT011003";

        internal string ErrorCode { get; private set; }
        internal string Description { get; private set; }

        public RemoteException(string errorCode, string description)
            : base(Combine(errorCode, description))
        {
            ErrorCode = errorCode;
            Description = description;
        }

        public RemoteException(string errorCode, string description, System.Exception nestedException)
            : base(Combine(errorCode, description), nestedException)
        {
            ErrorCode = errorCode;
            Description = description;
        }

        private static string Combine(string errorCode, string description)
        {
            return $"Remote server returned an error: [{errorCode}] {description}";
        }

        internal static RemoteException CreateNew(string errorCode, string description, System.Exception nested = null)
        {
            if (string.Compare(errorCode, NO_OBJECTS_FOR_EXPORT) == 0)
            {
                return new NoResultsRemoteException(errorCode, description, nested);
            }
            return new RemoteException(errorCode, description);
        }

        internal static RemoteException CreateNew(RemoteException nested)
        {
            if (nested == null)
            {
                throw new ArgumentNullException(nameof(nested));
            }
            return CreateNew(nested.ErrorCode, nested.Description, nested);
        }

        /// <summary>
        /// Возвращает true, если ошибка @e или ее вложенные ошибки содержат @errorCode
        /// </summary>
        internal static bool ContainsErrorCode(SystemException e, string errorCode)
        {
            if (e == null)
            {
                return false;
            }
            return Util.EnumerateInnerExceptions(e).OfType<RemoteException>().Where(x => x.ErrorCode == errorCode).Any();
        }
    }
}
