using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;
using System.IO;
using System.Threading;
using log4net.Appender;
using log4net.Config;
using log4net;
using log4net.Layout;
using Concilium.Bot;
using Concilium.Helpers;
using System.Net;
using System.Diagnostics;

namespace Concilium
{
    public class App
    {
        public static void Main(string[] args)
        {
            Thread.CurrentThread.Name = "Main";
            Console.BufferWidth = 120;
            Console.BufferHeight = 1000;
            Console.WindowWidth = 120;

            var directory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Concilium");

            var allConsoleAppender = new ColoredConsoleAppender();
            allConsoleAppender.Layout = new PatternLayout("%message (%logger)%newline");
            var debugMapping = new log4net.Appender.ColoredConsoleAppender.LevelColors()
            {
                Level = log4net.Core.Level.Debug,
                ForeColor = ColoredConsoleAppender.Colors.HighIntensity
            };
            var infoMapping = new log4net.Appender.ColoredConsoleAppender.LevelColors()
            {
                Level = log4net.Core.Level.Info,
                ForeColor = ColoredConsoleAppender.Colors.White
            };
            var warningMapping = new log4net.Appender.ColoredConsoleAppender.LevelColors()
            {
                Level = log4net.Core.Level.Warn,
                ForeColor = ColoredConsoleAppender.Colors.Yellow
            };
            var errorMapping = new log4net.Appender.ColoredConsoleAppender.LevelColors()
            {
                Level = log4net.Core.Level.Error,
                ForeColor = ColoredConsoleAppender.Colors.Red
            };
            var fatalMapping = new log4net.Appender.ColoredConsoleAppender.LevelColors()
            {
                Level = log4net.Core.Level.Fatal,
                BackColor = ColoredConsoleAppender.Colors.Red,
                ForeColor = ColoredConsoleAppender.Colors.Yellow
            };
            allConsoleAppender.AddMapping(debugMapping);
            allConsoleAppender.AddMapping(infoMapping);
            allConsoleAppender.AddMapping(warningMapping);
            allConsoleAppender.AddMapping(errorMapping);
            allConsoleAppender.AddMapping(fatalMapping);
            var levelRangeFilter = new log4net.Filter.LevelRangeFilter();
            levelRangeFilter.LevelMin = log4net.Core.Level.Info;
            levelRangeFilter.LevelMax = log4net.Core.Level.Off;
            var noMessageTypesFilter = new log4net.Filter.LoggerMatchFilter();
            noMessageTypesFilter.LoggerToMatch = "MESSAGETYPES";
            noMessageTypesFilter.AcceptOnMatch = false;
            noMessageTypesFilter.Next = levelRangeFilter;
            var noConciliumFilter = new log4net.Filter.LoggerMatchFilter();
            noConciliumFilter.LoggerToMatch = Log.Get().Logger.Name;
            noConciliumFilter.AcceptOnMatch = false;
            noConciliumFilter.Next = noMessageTypesFilter;
            allConsoleAppender.AddFilter(noConciliumFilter);
            allConsoleAppender.ActivateOptions();

            var conciliumConsoleAppender = new ColoredConsoleAppender();
            var conciliumFilter = new log4net.Filter.LoggerMatchFilter();
            conciliumFilter.LoggerToMatch = Log.Get().Logger.Name;
            conciliumFilter.AcceptOnMatch = true;
            conciliumFilter.Next = new log4net.Filter.DenyAllFilter();
            var ownMapping = new log4net.Appender.ColoredConsoleAppender.LevelColors()
            {
                Level = log4net.Core.Level.Info,
                ForeColor = ColoredConsoleAppender.Colors.Cyan
            };
            var ownErrorMapping = new log4net.Appender.ColoredConsoleAppender.LevelColors()
            {
                Level = log4net.Core.Level.Error,
                ForeColor = ColoredConsoleAppender.Colors.Red
            };
            conciliumConsoleAppender.AddMapping(ownMapping);
            conciliumConsoleAppender.AddMapping(errorMapping);
            conciliumConsoleAppender.AddMapping(fatalMapping);
            conciliumConsoleAppender.AddMapping(warningMapping);
            conciliumConsoleAppender.AddFilter(conciliumFilter);
            conciliumConsoleAppender.Layout = new PatternLayout("%message%newline");
            conciliumConsoleAppender.ActivateOptions();

            var fileAppender = new FileAppender();
            fileAppender.File = Path.Combine(directory, "Concilium.log");
            fileAppender.Layout = new PatternLayout("%timestamp [%thread] %-5level %logger - %message%newline");
            fileAppender.ActivateOptions();

            BasicConfigurator.Configure(new IAppender[] { conciliumConsoleAppender, allConsoleAppender, fileAppender });

            var concilium = new Concilium.Bot.Concilium();

            ConsoleHelpers.SetConsoleCtrlHandler(new HandlerRoutine((t) =>
            {
                var isclosing = false;
                switch (t)
                {
                    case CtrlTypes.CTRL_C_EVENT:
                        isclosing = true;
                        Console.WriteLine("CTRL+C received!");
                        break;

                    case CtrlTypes.CTRL_BREAK_EVENT:
                        isclosing = true;
                        Console.WriteLine("CTRL+BREAK received!");
                        break;

                    case CtrlTypes.CTRL_CLOSE_EVENT:
                        isclosing = true;
                        Console.WriteLine("Program being closed!");
                        break;

                    case CtrlTypes.CTRL_LOGOFF_EVENT:
                    case CtrlTypes.CTRL_SHUTDOWN_EVENT:
                        isclosing = true;
                        Console.WriteLine("User is logging off!");
                        break;
                }

                if (isclosing && concilium != null)
                {
                    try
                    {
                        concilium.Save();
                        concilium = null;
                    }
                    catch (Exception)
                    {
                    }
                }

                return true;
            }), true);

            concilium.Run();
        }
    }
}
