﻿using System;
using System.IO;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.PlatformAbstractions;
using Serilog;
using Serilog.Core;
using Serilog.Events;
using ILogger = Microsoft.Extensions.Logging.ILogger;

namespace Trinity.Infrastructure
{
	public class Logging
	{
		private static readonly Lazy<ILoggerFactory> Factory = new Lazy<ILoggerFactory>(() => ConfigureLogger(new LoggerFactory()));

		//TODO: Change default log level once 'stable'
		private static readonly LoggingLevelSwitch Level = new LoggingLevelSwitch(LogEventLevel.Debug);

		public static void SetLoggingLevel(string level)
		{
			switch (level)
			{
				case "trace":
					Level.MinimumLevel = LogEventLevel.Verbose;
					break;
				case "debug":
					Level.MinimumLevel = LogEventLevel.Debug;
					break;
				case "info":
					Level.MinimumLevel = LogEventLevel.Information;
					break;
				default:
					Level.MinimumLevel = LogEventLevel.Error;
					break;
			}
			Default.LogInformation("{method}, New Log Level: {logLevel}", "SetLoggingLevel", Level.MinimumLevel);
		}

		public static ILoggerFactory LoggerFactory => Factory.Value;

		private static ILoggerFactory ConfigureLogger(ILoggerFactory factory)
		{
			var config = new LoggerConfiguration()
				.MinimumLevel.ControlledBy(Level)
				.WriteTo.Console(outputTemplate: "[{SourceContext:l}:{Timestamp:HH:mm:ss}]-[{Level}] {Message}{NewLine}{Exception}")
				.WriteTo.RollingFile(Path.Combine(PlatformServices.Default.Application.ApplicationBasePath, "data/logs/trinity-errors-{Date}.txt"), LogEventLevel.Error)
				.WriteTo.RollingFile(Path.Combine(PlatformServices.Default.Application.ApplicationBasePath, "data/logs/trinity-{Date}.txt"));

			factory
				.AddSerilog(config.CreateLogger());

			return factory;
		}

		public static ILogger Default => LoggerFactory.CreateLogger("Default");

		public static ILogger Cli => LoggerFactory.CreateLogger("CLI");

		public static ILogger RemoteNode => LoggerFactory.CreateLogger("RemoteNode");

		public static ILogger LocalNode => LoggerFactory.CreateLogger("LocalNode");

		public static ILogger LocalNodeOutgoing => LoggerFactory.CreateLogger("LocalNode.Outgoing");

		public static ILogger LocalNodeIncomming => LoggerFactory.CreateLogger("LocalNode.Incomming");

		public static ILogger Consensus => LoggerFactory.CreateLogger("Consensus");
	}
}