using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;

namespace MeterVision.Util
{
    public class LogHelper
    {
        public static Action<LogType, string> ReceiveErrorLog;
        /// <summary>
        /// 限制文件生成大小，258000字节,大约253kb
        /// </summary>
        private const long fileBytes = 258000;

        private static string GetNewFileName(string fileFolderPath,string filetype ,string fileNameNoExtension)
        {
            string fileName = string.Empty;
            if (fileNameNoExtension.LastIndexOf('_') == -1)
            {
                int index = 1;
                fileName = fileFolderPath + "\\" + filetype + DateTime.Now.ToString("yyyy-MM-dd") + "_" + index + ".txt";
                while (File.Exists(fileName))
                {
                    if (File.ReadAllBytes(fileName).Length < fileBytes)
                    {
                        break;
                    }
                    index++;
                    fileName = fileFolderPath + "\\" + filetype + DateTime.Now.ToString("yyyy-MM-dd") + "_" + index + ".txt";
                }
            }
            else
            {
                int index = 1;
                int.TryParse(fileNameNoExtension.Split('_')[2], out index);
                if (index == 0)
                {
                    index = 1;
                }
                fileName = fileFolderPath + "\\" + filetype + DateTime.Now.ToString("yyyy-MM-dd") + "_" + index + ".txt";
                while (File.Exists(fileName))
                {
                    if (File.ReadAllBytes(fileName).Length < fileBytes)
                    {
                        break;
                    }
                    index++;
                    fileName = fileFolderPath + "\\" + filetype + DateTime.Now.ToString("yyyy-MM-dd") + "_" + index + ".txt";
                }
            }

            return fileName;
        }

        /// <summary>  
        /// 日志记录，在程序执行的根目录，写入txt文件，文件固定大小，超过限定大小自动创建新日志文件
        /// </summary>  
        /// <param name="msg">记录内容</param>  
        /// <returns></returns>  
        private static void AddLog(string filetype,string msg)
        {
            string saveFolder = "Log";//日志文件保存路径   
            try
            {
                string fileFolderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, saveFolder);
                if (Directory.Exists(fileFolderPath) == false)
                {
                    Directory.CreateDirectory(fileFolderPath);
                }
                string fileName = string.Empty;
                string[] files = Directory.GetFiles(fileFolderPath, filetype + "*");
                if (files.Length == 0)
                {
                    fileName = fileFolderPath + "\\" + filetype + DateTime.Now.ToString("yyyy-MM-dd") + "_1.txt";
                    //goto DO_WRITE;
                }
                else
                {
                    string[] files2 = files.OrderByDescending(x => x).ToArray();
                    FileInfo fileInfo = new FileInfo(files2[0]);
                    string fileNameNoExtension = Path.GetFileNameWithoutExtension(fileInfo.Name);
                    if (fileInfo.Length > fileBytes)
                    {
                        fileName = GetNewFileName(fileFolderPath,filetype,fileNameNoExtension);
                    }
                    else
                    {
                        fileName = GetNewFileName(fileFolderPath,filetype,fileNameNoExtension);
                    }
                }
            //DO_WRITE:
                FileStream fs = new FileStream(fileName, FileMode.Append);
                string time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
                msg = time + ">" + msg + System.Environment.NewLine;
                byte[] logBytes = UTF8Encoding.UTF8.GetBytes(msg);
                fs.Write(logBytes, 0, logBytes.Length);
                fs.Flush();
                fs.Close();
                fs.Dispose();
                //  tishiMsg = "写入日志成功";
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }


        public static void WriteErrLog(Exception ex)
        {
            string sMsg = string.Format("[消息]:{0}\r\n[跟踪]:{1}", ex.Message, ex.StackTrace);
            //mErrLog.Info(sMsg);
            AddLog(LogType.Error, ex.Message);
        }

        /// <summary>
        /// 增加日志 1:普通日志 2:警告日志 3:http错误日志 4:奔溃日志 5:MQ消息日志
        /// </summary>
        /// <param name="msg"></param>
        public static void AddLog(LogType logType,string msg)
        {
            string filetype = "info_";
            string msgTitle = "";
            switch (logType)
            {
                case LogType.Normal:
                    msgTitle = " INFO ";
                    filetype = "info_";
                    break;
                case LogType.Error:
                    msgTitle = " ERROR ";
                    filetype = "error_";
                    break;
                case LogType.HttpError:
                    msgTitle = " HTTP_ERRO ";
                    filetype = "httperror_";
                    break;
                case LogType.Mq:
                    msgTitle = " MQ ";
                    filetype = "mq_";
                    break;
                case LogType.MqError:
                    msgTitle = " MQ_ERROR ";
                    filetype = "mq_";
                    break;
                case LogType.Crash:
                    msgTitle = " CRASH ";
                    filetype = "crash_";
                    break;
            }
            msg = msgTitle +  GetStack() + " " + msg;
            AddLog(filetype ,msg);
            if(logType == LogType.Error || logType == LogType.HttpError || logType == LogType.MqError)
            {
                //ReceiveErrorLog?.Invoke(logType, msg);
            }
        }

        public static string GetStack()
        {
            StackTrace trace = new StackTrace();
            //获取是那个类来调用的
            string classname = trace.GetFrame(2).GetMethod().DeclaringType.Name;
            //获取是那个类中的方法调用的
            string method = trace.GetFrame(2).GetMethod().ToString();

            return $"{classname} [{method}]";
        }

        //        在 System.Reflection命名空间下的 MethodBase类

        //该类 提供有关方法和构造函数的信息。

        //GetCurrentMethod() 是一个静态方法，从一个执行方法中调用，且会返回有关该方法的信息。

        //表示当前的执行方法的 MethodBase 对象。

        //public static System.Reflection.MethodBase GetCurrentMethod();
　　      //  1.获取当前执行方法的类名

        //System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name;
　　      //  2.获取当前成员的名称

        //System.Reflection.MethodBase.GetCurrentMethod().Name;
        ////////////////////////////////////////////////////////////////////////////////
    }
}
