using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using log4net;
using log4net.Appender;
using log4net.Core;
using log4net.Config;

namespace ChuPiao.Common.Utils
{
    /// <summary>
    /// 日志工具类
    /// </summary>
    public class LogUtil
    {
        public static IAppender[] RawAppenders;
        private static ILog _logger;

        /// <summary>
        /// 配置log4net
        /// </summary>
        public static void Setup()
        {
            Setup(Path.Combine("Configs", "Log4net.xml"));
        }
        public static void Setup(string log4NetConfig)
        {
            if (!Path.IsPathRooted(log4NetConfig))
                log4NetConfig = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, log4NetConfig);

            XmlConfigurator.Configure(new FileInfo(log4NetConfig));
            //系统日志记录器
            _logger = LogManager.GetLogger("default");

            //获取system日志的Appenders
            //_rawAppenders = log4net.LogManager.GetRepository().GetAppenders();
            //都是在system的appender的基础上进行复制，而不是所有appender
            RawAppenders = _logger.Logger.Repository.GetAppenders();
        }
        /// <summary>
        /// 获取系统全局日志记录器
        /// </summary>
        /// <returns></returns>
        public static ILog GetRootLogger()
        {
            return _logger;
        }

        public static void LogError(Exception e)
        {
            if (_logger != null)
                _logger.Error(e);
        }

        public static void LogError(string title, Exception e)
        {
            if (_logger != null)
                _logger.Error(title, e);
        }

        public static void LogError(string message)
        {
            if (_logger != null)
                _logger.Error(message);
        }

        public static void LogWarn(string message)
        {
            if (_logger != null)
                _logger.Warn(message);
        }

        public static void LogDebug(string message)
        {
            if (_logger != null)
                _logger.Debug(message);
        }

        public static void LogInfo(string message)
        {
            if (_logger != null)
                _logger.Info(message);
        }
        /// <summary>
        /// 记录性能日志
        /// </summary>
        /// <param name="message"></param>
        public static void LogPerf(string message)
        {
            if (_logger != null)
            {
                LoggingEventData loggingEventData = new LoggingEventData();
                loggingEventData.LoggerName = _logger.Logger.Name;
                loggingEventData.Message = message;
                loggingEventData.Level = Level.Trace;
                loggingEventData.TimeStamp = DateTime.Now;
                loggingEventData.Domain = AppDomain.CurrentDomain.FriendlyName;
                _logger.Logger.Log(new LoggingEvent(loggingEventData));
            }
        }

        /// <summary>
        /// 根据名称动态创建一个日志记录器（日志路径规则：应用程序目录\Logs\yyyy-MM-dd\日志记录器名称\日志级别(debug/info/err)\HH.txt）
        /// </summary>
        /// <param name="loggerName"></param>
        /// <returns></returns>
        public static ILog CreateLoggerByName(string loggerName)
        {
            //GetLogger找不到loggerName就会创建一个
            ILog logger = LogManager.GetLogger(loggerName);

            log4net.Repository.Hierarchy.Logger currentLogger = logger.Logger as log4net.Repository.Hierarchy.Logger;
            currentLogger.Additivity = false;//disable root appender for this logger

            foreach (IAppender ap in RawAppenders)
            {
                ////使用共享的 perf appender
                //if (ap.Name==null || ap.Name.StartsWith("perf", StringComparison.OrdinalIgnoreCase))
                //{
                //    currentLogger.AddAppender(ap);
                //    continue;
                //}
                //克隆FileAppender
                RollingFileAppender appender = ap as RollingFileAppender;
                if (appender.FilterHead == null)   //排除系统的4个appender
                    continue;

                RollingFileAppender rollingFileAppender = CloneAppender(appender, loggerName);
                if (rollingFileAppender == null)
                    continue;

                rollingFileAppender.File = ProcessLogFilePath(rollingFileAppender.File);
                currentLogger.AddAppender(rollingFileAppender);
                rollingFileAppender.ActivateOptions();
            }
            return logger;
        }

        private static string ProcessLogFilePath(string rawFilePath)
        {
            //string[] fileNodes = rawFilePath.Split('/', '\\');
            //string[] newFileNodes = new string[fileNodes.Length + 1];
            //Array.Copy(fileNodes, 0, newFileNodes, 0, fileNodes.Length - 1);
            //newFileNodes[fileNodes.Length - 1] = Name;
            //Array.Copy(fileNodes, fileNodes.Length - 1, newFileNodes, newFileNodes.Length - 1, 1);
            //return string.Join(Path.DirectorySeparatorChar.ToString(), newFileNodes);

            string[] fileNodes = rawFilePath.Split('/', '\\');
            string[] newFileNodes = new string[fileNodes.Length - 4];
            Array.Copy(fileNodes, 0, newFileNodes, 0, fileNodes.Length - 4);
            return string.Join(Path.DirectorySeparatorChar.ToString(), newFileNodes);
        }

        /// <summary>
        /// 为日志记录器添加MemoryAppender
        /// </summary>
        /// <param name="logger"></param>
        /// <param name="memoryAppender"></param>
        public static void AddMemoryAppender(ILog logger, MemoryAppender memoryAppender)
        {
            log4net.Repository.Hierarchy.Logger currentLogger = logger.Logger as log4net.Repository.Hierarchy.Logger;
            if (currentLogger != null && !currentLogger.Appenders.Contains(memoryAppender))
            {
                currentLogger.AddAppender(memoryAppender);
            }
        }

        /// <summary>
        /// 按日志名称获取最新日志内容
        /// </summary>
        /// <param name="loggerName"></param>
        /// <returns></returns>
        public static List<string> GetLastLogContentByName(string loggerName)
        {
            /*List<string> result=new List<string>();
            DateTime currentTime = DateTime.Now;
            string fileName=string.Format(@"Logs\{0}\{1}\info\{2}.txt", currentTime.ToString("yyyy-MM-dd"),loggerName, currentTime.ToString("HH"));
            string filePath = Path.Combine(ApplicationUtil.GetHomePath(), fileName);
            if (File.Exists(filePath))
            {
                //只读打开文件
                using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                {
                    using (StreamReader streamReader = new StreamReader(fileStream, Encoding.GetEncoding("gb2312")))
                    {
                        string nextLine;
                        while ((nextLine = streamReader.ReadLine())!=null)
                        {
                            result.Add(nextLine);
                        }
                    }
                }
            }
            return result;*/


            List<string> result = new List<string>();
            log4net.Repository.Hierarchy.Logger logger = LogManager.GetLogger(loggerName).Logger as log4net.Repository.Hierarchy.Logger;
            if (logger == null)
            {
                return result;
            }
            string filePath = null;
            foreach (IAppender appender in logger.Appenders)
            {
                if (appender is FileAppender)
                {
                    FileAppender fa = appender as FileAppender;
                    filePath = fa.File;
                    break;
                }
            }
            if (filePath != null && File.Exists(filePath))
            {
                //只读打开文件
                using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                {
                    using (StreamReader streamReader = new StreamReader(fileStream, Encoding.GetEncoding("gb2312")))
                    {
                        string nextLine;
                        while ((nextLine = streamReader.ReadLine()) != null)
                        {
                            result.Add(nextLine);
                        }
                    }
                }
            }
            return result;
        }
        /// <summary>
        /// 克隆Appender对象
        /// </summary>
        /// <param name="appender"></param>
        /// <param name="loggerName"></param>
        /// <returns></returns>
        private static RollingFileAppender CloneAppender(RollingFileAppender appender, string loggerName)
        {
            RollingFileAppender newAppender = new RollingFileAppender();
            newAppender.Name = appender.Name;
            newAppender.RollingStyle = appender.RollingStyle;
            newAppender.StaticLogFileName = appender.StaticLogFileName;
            newAppender.Threshold = appender.Threshold;
            newAppender.MaxSizeRollBackups = appender.MaxSizeRollBackups;
            newAppender.MaximumFileSize = appender.MaximumFileSize;
            newAppender.MaxFileSize = appender.MaxFileSize;
            //newAppender.LockingModel = appender.LockingModel;
            newAppender.Layout = appender.Layout;
            newAppender.ImmediateFlush = appender.ImmediateFlush;
            newAppender.File = appender.File;
            newAppender.ErrorHandler = appender.ErrorHandler;
            newAppender.Encoding = appender.Encoding;
            //newAppender.DatePattern = appender.DatePattern;
            newAppender.DatePattern = appender.DatePattern.Replace("'default'", "'" + loggerName + "'");
            newAppender.CountDirection = appender.CountDirection;
            newAppender.AppendToFile = appender.AppendToFile;
            newAppender.AddFilter(appender.FilterHead);
            return newAppender;
        }
        
    }
}
