using System;
using System.Collections.Generic;
using System.Linq;

namespace Websocket.Client.Logging.LogProviders
{
	internal abstract class LogProviderBase : ILogProvider
	{
		protected LogProviderBase()
		{
			this._lazyOpenNdcMethod = new Lazy<LogProviderBase.OpenNdc>(new Func<LogProviderBase.OpenNdc>(this.GetOpenNdcMethod));
			this._lazyOpenMdcMethod = new Lazy<LogProviderBase.OpenMdc>(new Func<LogProviderBase.OpenMdc>(this.GetOpenMdcMethod));
		}

		public abstract Logger GetLogger(string name);

		public IDisposable OpenNestedContext(string message)
		{
			return this._lazyOpenNdcMethod.Value(message);
		}

		public IDisposable OpenMappedContext(string key, object value, bool destructure = false)
		{
			return this._lazyOpenMdcMethod.Value(key, value, destructure);
		}

		protected virtual LogProviderBase.OpenNdc GetOpenNdcMethod()
		{
			return (string _) => LogProviderBase.NoopDisposableInstance;
		}

		protected virtual LogProviderBase.OpenMdc GetOpenMdcMethod()
		{
			return (string _, object __, bool ___) => LogProviderBase.NoopDisposableInstance;
		}

		protected static Type FindType(string typeName, string assemblyName)
		{
			return LogProviderBase.FindType(typeName, new string[] { assemblyName });
		}

		protected static Type FindType(string typeName, IReadOnlyList<string> assemblyNames)
		{
			return assemblyNames.Select((string assemblyName) => Type.GetType(typeName + ", " + assemblyName)).FirstOrDefault((Type type) => type != null) ?? Type.GetType(typeName);
		}

		private static readonly IDisposable NoopDisposableInstance = new DisposableAction(null);

		private readonly Lazy<LogProviderBase.OpenMdc> _lazyOpenMdcMethod;

		protected const string ErrorInitializingProvider = "Unable to log due to problem initializing the log provider. See inner exception for details.";

		private readonly Lazy<LogProviderBase.OpenNdc> _lazyOpenNdcMethod;

		protected delegate IDisposable OpenNdc(string message);

		protected delegate IDisposable OpenMdc(string key, object value, bool destructure);
	}
}
