namespace LigLogOwin
{
    using System;
    using System.Diagnostics;
    using LibLogOwin.Logging;
    using Microsoft.Owin.Logging;
    using Owin;

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.SetLoggerFactory(new LibLogLoggerFactory());
        }

        private class LibLogLoggerFactory : ILoggerFactory
        {
            public ILogger Create(string name)
            {
                return new LibLogLogger(LogProvider.GetLogger(name));
            }

            private class LibLogLogger : ILogger
            {
                private readonly ILog _logger;

                public LibLogLogger(ILog logger)
                {
                    _logger = logger;
                }

                public bool WriteCore(
                    TraceEventType eventType,
                    int eventId,
                    object state,
                    Exception exception,
                    Func<object, Exception, string> formatter)
                {
                    return state == null
                        ? _logger.Log(Map(eventType), null) // Equivalent to IsLogLevelXEnabled 
                        //TODO What to do with eventId?
                        : _logger.Log(Map(eventType), () => formatter(state, exception), exception); 
                }

                private LogLevel Map(TraceEventType eventType)
                {
                    switch(eventType)
                    {
                        case TraceEventType.Critical:
                            return LogLevel.Fatal;
                        case TraceEventType.Error:
                            return System.LogLevel.Error;
                        case TraceEventType.Warning:
                            return LogLevel.Warn;
                        case TraceEventType.Information:
                            return LogLevel.Info;
                        case TraceEventType.Verbose:
                            return System.LogLevel.Trace;
                        case TraceEventType.Start:
                            return LogLevel.Info;
                        case TraceEventType.Stop:
                            return LogLevel.Info;
                        case TraceEventType.Suspend:
                            return LogLevel.Info;
                        case TraceEventType.Resume:
                            return LogLevel.Info;
                        case TraceEventType.Transfer:
                            return LogLevel.Info;
                        default:
                            throw new ArgumentOutOfRangeException("eventType");
                    }
                }
            }
        }
    }
}