using MrWu.Time;
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace MrWu.Debug
{
    /// <summary>
    /// 日志控件
    /// </summary>
    public partial class DebugControl : UserControl
    {
        
        /// <summary>
        /// 创建日志控件
        /// </summary>
        public DebugControl() : this(null) {
        }

        /// <summary>
        /// 日志配置
        /// </summary>
        public LogConfig config {
            get;
            private set;
        }

        /// <summary>
        /// 日志控件
        /// </summary>
        public DebugControl(LogConfig config) {
            this.config = config;
            if (this.config == null)
                this.config = getDefaultConfig();
            InitializeComponent();
        }

        /// <summary>
        /// 获取默认配置
        /// </summary>
        /// <returns></returns>
        private LogConfig getDefaultConfig() {
            return new LogConfig() {
                //logpath = DateTime.Now.TimeToString(TimeStyle.MMddhhmmss, string.Empty, string.Empty, string.Empty) + ".log"
            };
        }

        /// <summary>
        /// 日志等级
        /// </summary>
        private DebugLevel level {
            get {
                return Debug.logLevel;
            }
        }

        private void LogLevelChange(object sender, EventArgs e) {
            //CheckBox cb = sender as CheckBox;
            //if (cb != null) {
            //    string tag = cb.Tag as string;
            //    switch (tag) {
            //        case "log":
            //            if (cb.Checked)
            //                level = level | DebugLevel.Log;
            //            else
            //                level = level & ~DebugLevel.Log;
            //            break;
            //        case "warning":
            //            if (cb.Checked)
            //                level = level | DebugLevel.Warning;
            //            else
            //                level = level & ~DebugLevel.Warning;
            //            break;
            //        case "error":
            //            if (cb.Checked)
            //                level = level | DebugLevel.Error;
            //            else
            //                level = level & ~DebugLevel.Error;
            //            break;
            //        default:
            //            return;
            //    }
            //    textBox1.Clear();
            //    //ClearMemory();
            //}
        }

        ///// <summary>
        ///// SetProcessWorkingSetSize
        ///// </summary>
        ///// <param name="process"></param>
        ///// <param name="minSize"></param>
        ///// <param name="maxSize"></param>
        ///// <returns></returns>
        //[DllImport("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize")]
        //public static extern int SetProcessWorkingSetSize(IntPtr process, int minSize, int maxSize);

        ///// <summary>
        ///// 释放内存 
        ///// </summary>
        //public static void ClearMemory() {
        //    GC.Collect();
        //    GC.WaitForPendingFinalizers();
        //    if(Environment.OSVersion.Platform == PlatformID.Win32NT) {
        //        SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
        //    }
        //}

        private int logMaxLength = 20000;

        private void timer1_Tick(object sender, EventArgs e) {
            textBox1.AppendText(LogPool.GetLog(level));
            if (textBox1.TextLength > logMaxLength) {
                textBox1.Text = textBox1.Text.Remove(0, textBox1.TextLength - logMaxLength / 2);
            }
            RefreshLog();

            label1.Text = $"警告:{LogPool.warningCount},错误:{LogPool.errorCount},致命错误:{LogPool.fatalCount}";
        }

        private void RefreshLog() {
            //foreach(var ctl in flowLayoutPanel1.Controls) {
            //    var cc = ctl as Control;

            //    if(cc != null) {
            //        string tag = cc.Tag as string;
            //        switch(tag) {
            //            case "logCount":
            //                cc.Text = LogPool.logCount.ToString("N0");
            //                break;
            //            case "warningCount":
            //                cc.Text = LogPool.warningCount.ToString("N0");
            //                break;
            //            case "errorCount":
            //                cc.Text = LogPool.errorCount.ToString("N0");
            //                break;
            //        }

            //    }

            //}
        }

        private void DebugControl_Load(object sender, EventArgs e) {
            LogPool.Start(config);
            RefreshLogLevel(null); //启动的时候刷新
            Debug.LogLevelChange += LogLevelChange;
            LogPool.SaveLevelChange += LogLevelChange;
        }

        private void LogLevelChange(DebugLevel level) {
            Action< ToolStripMenuItem> action = RefreshLogLevel;
            this.BeginInvoke(action,new object[]{ null});
        }

        private void ToolStripMenuItem_Click(object sender, EventArgs e) {
            var item = sender as ToolStripMenuItem;
            if (item == null)
                return;
            var tag = item.Tag as string;
            if (string.IsNullOrEmpty(tag))
                return;
            //item.Checked = !item.Checked;
            var lastlevel = Debug.logLevel;
            switch (tag) {
                case "logPrint":
                    if (!item.Checked)
                        Debug.logLevel = Debug.logLevel | DebugLevel.Log;
                    else
                        Debug.logLevel = Debug.logLevel & ~DebugLevel.Log;
                    break;
                case "logSave":
                    if (!item.Checked)
                        LogPool.saveLevel = LogPool.saveLevel | DebugLevel.Log;
                    else
                        LogPool.saveLevel = LogPool.saveLevel & ~DebugLevel.Log;
                    break;
                case "infoPrint":
                    if (!item.Checked)
                        Debug.logLevel = Debug.logLevel | DebugLevel.Info;
                    else
                        Debug.logLevel = Debug.logLevel & ~DebugLevel.Info;
                    break;
                case "InfoSave":
                    if (!item.Checked)
                        LogPool.saveLevel = LogPool.saveLevel | DebugLevel.Info;
                    else
                        LogPool.saveLevel = LogPool.saveLevel & ~DebugLevel.Info;
                    break;
                case "WarningPrint":
                    if (!item.Checked)
                        Debug.logLevel = Debug.logLevel | DebugLevel.Warning;
                    else
                        Debug.logLevel = Debug.logLevel & ~DebugLevel.Warning;
                    break;
                case "WarningSave":
                    if (!item.Checked)
                        LogPool.saveLevel = LogPool.saveLevel | DebugLevel.Warning;
                    else
                        LogPool.saveLevel = LogPool.saveLevel & ~DebugLevel.Warning;
                    break;
                case "ImportantLogPrint":
                    if (!item.Checked)
                        Debug.logLevel = Debug.logLevel | DebugLevel.ImportantLog;
                    else
                        Debug.logLevel = Debug.logLevel & ~DebugLevel.ImportantLog;
                    break;
                case "ImportantLogSave":
                    if (!item.Checked)
                        LogPool.saveLevel = LogPool.saveLevel | DebugLevel.ImportantLog;
                    else
                        LogPool.saveLevel = LogPool.saveLevel & ~DebugLevel.ImportantLog;
                    break;
                case "ErrorPrint":
                    if (!item.Checked)
                        Debug.logLevel = Debug.logLevel | DebugLevel.Error;
                    else
                        Debug.logLevel = Debug.logLevel & ~DebugLevel.Error;
                    break;
                case "ErrorSave":
                    if (!item.Checked)
                        LogPool.saveLevel = LogPool.saveLevel | DebugLevel.Error;
                    else
                        LogPool.saveLevel = LogPool.saveLevel & ~DebugLevel.Error;
                    break;
                case "FatalPrint":
                    if (!item.Checked)
                        Debug.logLevel = Debug.logLevel | DebugLevel.Fatal;
                    else
                        Debug.logLevel = Debug.logLevel & ~DebugLevel.Fatal;
                    break;
                case "FatalSave":
                    if (!item.Checked)
                        LogPool.saveLevel = LogPool.saveLevel | DebugLevel.Fatal;
                    else
                        LogPool.saveLevel = LogPool.saveLevel & ~DebugLevel.Fatal;
                    break;
            }
            if (Debug.logLevel != lastlevel)
                textBox1.Clear();
        }

        private void RefreshLogLevel(ToolStripMenuItem myTsm) {
            ToolStripItemCollection tsic = null;
            if (myTsm != null) {
                tsic = myTsm.DropDownItems;
            } else {
                tsic = menuStrip1.Items;
            }

            foreach (var item in tsic) {
                var tsm = item as ToolStripMenuItem;

                if (tsm != null) {
                    string tag = tsm.Tag as string;
                    switch (tag) {
                        case "logPrint":
                            tsm.Checked = (Debug.logLevel & DebugLevel.Log) != 0;
                            break;
                        case "logSave":
                            tsm.Checked = (LogPool.saveLevel & DebugLevel.Log) != 0;
                            break;
                        case "infoPrint":
                            tsm.Checked = (Debug.logLevel & DebugLevel.Info) != 0;
                            break;
                        case "InfoSave":
                            tsm.Checked = (LogPool.saveLevel & DebugLevel.Info) != 0;
                            break;
                        case "WarningPrint":
                            tsm.Checked = (Debug.logLevel & DebugLevel.Warning) != 0;
                            break;
                        case "WarningSave":
                            tsm.Checked = (LogPool.saveLevel & DebugLevel.Warning) != 0;
                            break;
                        case "ImportantLogPrint":
                            tsm.Checked = (Debug.logLevel & DebugLevel.ImportantLog) != 0;
                            break;
                        case "ImportantLogSave":
                            tsm.Checked = (LogPool.saveLevel & DebugLevel.ImportantLog) != 0;
                            break;
                        case "ErrorPrint":
                            tsm.Checked = (Debug.logLevel & DebugLevel.Error) != 0;
                            break;
                        case "ErrorSave":
                            tsm.Checked = (LogPool.saveLevel & DebugLevel.Error) != 0;
                            break;
                        case "FatalPrint":
                            tsm.Checked = (Debug.logLevel & DebugLevel.Fatal) != 0;
                            break;
                        case "FatalSave":
                            tsm.Checked = (LogPool.saveLevel & DebugLevel.Fatal) != 0;
                            break;
                    }
                    RefreshLogLevel(tsm);
                }
            }
        }

        private void FlushToolStripMenuItem_Click(object sender, EventArgs e) {
            LogPool.Flush();
        }
    }
}
