/// Made by: Hebbo + Maarten, released by MoBaT [Under Permission].


using System;
using System.Diagnostics;
using System.Text;
using System.Threading;
using System.IO;

namespace Holo
{
    /// <summary>
    /// Provides interface output related functions, such as logging activities.
    /// </summary>
    public static class Out
    {
        /// <summary>
        /// Enum with flags for log importancies. If 'minimumImportance' flag is higher than the action to be logged, then the action won't be logged.
        /// </summary>
        public enum logFlags { ImportantAction = 3, StandardAction = 2, BelowStandardAction = 1, MehAction = 0 }
        /// <summary>
        /// Flag for minimum importance in logs. Adjust this to don't print less important logs.
        /// </summary>
        /// 
        private static Thread ErrorSaver = new Thread(new ThreadStart(WriteAllErrors));
        public static logFlags minimumImportance;
        private static bool bwait = false;
        private static int CurrentWaitingMessages = 0;
        private static StringBuilder ErrorQueue = new StringBuilder();
        //private static bool IsWriting = false;
        internal static bool savingErrors = false;
        // internal static FileStream Writer = new System.IO.FileStream(IO.workingDirectory + @"\Logs\Errorlog.log", System.IO.FileMode.Append, System.IO.FileAccess.Write);
        /// <summary>
        /// Prints a green line of log, together with timestamp and method name.
        /// </summary>
        /// <param name="logText">The log line to be printed.</param>
        public static void wait()
        {
            while (bwait) { Thread.Sleep(10); }
        }
        public static void WriteLine(string logText)
        {
            wait();
            bwait = true;
            DateTime _DTN = DateTime.Now;
            StackFrame _SF = new StackTrace().GetFrame(1);
            Console.Write("[" + _DTN.ToLongTimeString() + ":" + _DTN.Millisecond.ToString() + "] [");
            Console.ForegroundColor = ConsoleColor.Red;
            Console.Write(_SF.GetMethod().ReflectedType.Name + "." + _SF.GetMethod().Name);
            Console.ForegroundColor = ConsoleColor.Gray;
            Console.Write("] » ");
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine(logText);
            Console.ForegroundColor = ConsoleColor.Gray;
            bwait = false;
        }
        /// <summary>
        /// Prints a green line of log, together with timestamp and method name.
        /// </summary>
        /// <param name="logText">The log line to be printed.</param>
        /// <param name="logFlag">The importance flag of this log line.</param>
        public static void WriteLine(string logText, logFlags logFlag)
        {

            if ((int)logFlag < (int)minimumImportance)
                return;
            wait();
            bwait = true;
            DateTime _DTN = DateTime.Now;
            StackFrame _SF = new StackTrace().GetFrame(1);
            Console.Write("[" + _DTN.ToLongTimeString() + ":" + _DTN.Millisecond.ToString() + "] [");
            Console.ForegroundColor = ConsoleColor.Red;
            Console.Write(_SF.GetMethod().ReflectedType.Name + "." + _SF.GetMethod().Name);
            Console.ForegroundColor = ConsoleColor.Gray;
            Console.Write("] » ");
            Console.ForegroundColor = ConsoleColor.DarkRed;
            Console.WriteLine(logText);
            Console.ForegroundColor = ConsoleColor.Gray;
            bwait = false;
        }
        /// <summary>
        /// Prints a customizeable line of log, together with timestamp and method name.
        /// </summary>
        /// <param name="logText">The log line to be printed.</param>
        /// <param name="logFlag">The importance flag of this log line.</param>
        /// <param name="colorOne">The color to use on the left.</param>
        /// <param name="colorTwo">The color to use on the right.</param>
        public static void WriteLine(string logText, logFlags logFlag, ConsoleColor colorOne, ConsoleColor colorTwo)
        {

            if ((int)logFlag < (int)minimumImportance)
                return;
            wait();
            bwait = true;
            DateTime _DTN = DateTime.Now;
            StackFrame _SF = new StackTrace().GetFrame(1);
            Console.Write("[" + _DTN.ToLongTimeString() + ":" + _DTN.Millisecond.ToString() + "] [");
            Console.ForegroundColor = colorOne;
            Console.Write(_SF.GetMethod().ReflectedType.Name + "." + _SF.GetMethod().Name);
            Console.ForegroundColor = ConsoleColor.Gray;
            Console.Write("] » ");
            Console.ForegroundColor = colorTwo;
            Console.WriteLine(logText);
            Console.ForegroundColor = ConsoleColor.Gray;
            bwait = false;
        }
        public static void WriteTrace(string logText)
        {
            return;
            /*DateTime _DTN = DateTime.Now;
            StackFrame _SF = new StackTrace().GetFrame(1);
            Console.Write("[" + _DTN.ToLongTimeString() + ":" + _DTN.Millisecond.ToString() + "] [");
            Console.ForegroundColor = ConsoleColor.DarkMagenta;
            Console.Write(_SF.GetMethod().ReflectedType.Name + "." + _SF.GetMethod().Name);
            Console.ForegroundColor = ConsoleColor.Gray;
            Console.Write("] » ");
            Console.ForegroundColor = ConsoleColor.DarkMagenta;
            Console.WriteLine(logText);
            Console.ForegroundColor = ConsoleColor.Gray;*/
        }
        /// <summary>
        /// Prints a red, error line of log, together with timestamp and method name.
        /// </summary>
        /// <param name="logText">The log line to be printed.</param>
        public static void WriteError(string logText)
        {
            DateTime _DTN = DateTime.Now;
            StackFrame _SF = new StackTrace().GetFrame(1);

            Console.Write("[" + _DTN.ToLongTimeString() + ":" + _DTN.Millisecond.ToString() + "] [");
            Console.ForegroundColor = ConsoleColor.Red;
            Console.Write(_SF.GetMethod().ReflectedType.Name + "." + _SF.GetMethod().Name);
            Console.ForegroundColor = ConsoleColor.Gray;
            Console.Write("] » ");
            Console.ForegroundColor = ConsoleColor.DarkRed;
            Console.WriteLine(logText);
            Console.ForegroundColor = ConsoleColor.Gray;
        }
        /// <summary>
        /// Prints a red,error line of log, together with timestamp and method name.
        /// </summary>
        /// <param name="logText">The log line to be printed.</param>
        /// <param name="logFlag">The importance flag of this error.</param>
        public static void WriteError(string logText, logFlags logFlag)
        {
            if ((int)logFlag < (int)minimumImportance)
                return;

            DateTime _DTN = DateTime.Now;
            StackFrame _SF = new StackTrace().GetFrame(1);

            Console.Write("[" + _DTN.ToLongTimeString() + ":" + _DTN.Millisecond.ToString() + "] [");
            Console.ForegroundColor = ConsoleColor.Red;
            Console.Write(_SF.GetMethod().ReflectedType.Name + "." + _SF.GetMethod().Name);
            Console.ForegroundColor = ConsoleColor.Gray;
            Console.Write("] » ");
            Console.ForegroundColor = ConsoleColor.DarkRed;
            Console.WriteLine(logText);
            Console.ForegroundColor = ConsoleColor.Gray;
        }
        /// <summary>
        /// Writes a plain text line.
        /// </summary>
        /// <param name="logText">The log line to be printed.</param>
        public static void WritePlain(string logText)
        {
            wait();
            bwait = true;
            Console.WriteLine(logText);
            bwait = false;
        }
        /// <summary>
        /// Writes a blank line.
        /// </summary>
        public static void WriteBlank()
        {
            wait();
            bwait = true;
            Console.WriteLine();
            bwait = false;
        }
        /// <summary>
        /// Writes a special line of log, with customizeable colors and header coloring of logText.
        /// </summary>
        /// <param name="logText">The log line to be printed.</param>
        /// <param name="logFlag">The importance flag of this log line.</param>
        /// <param name="colorOne">The color to use on the left.</param>
        /// <param name="colorTwo">The color to use on the right.</param>
        /// <param name="headerHead">The string to use infront of logText.</param>
        /// <param name="headerLength">The length of the header to color.</param>
        /// <param name="headerColor">The color for the header in the logText.</param>
        public static void WriteSpecialLine(string logText, logFlags logFlag, ConsoleColor colorOne, ConsoleColor colorTwo, string headerHead, int headerLength, ConsoleColor headerColor)
        {
            //if ((int)logFlag < (int)minimumImportance)
            //return;
            wait();
            bwait = true;
            DateTime _DTN = DateTime.Now;
            StackFrame _SF = new StackTrace().GetFrame(1);
            Console.Write("[" + _DTN.ToLongTimeString() + ":" + _DTN.Millisecond.ToString() + "] [");
            Console.ForegroundColor = colorOne;
            Console.Write(_SF.GetMethod().ReflectedType.Name + "." + _SF.GetMethod().Name);
            Console.ForegroundColor = ConsoleColor.Gray;
            Console.Write("] " + headerHead + " ");
            Console.ForegroundColor = headerColor;
            try { Console.Write(logText.Substring(0, headerLength)); }
            catch { Console.Write(logText); }
            Console.ForegroundColor = colorTwo;
            Console.WriteLine(logText.Substring(headerLength));
            Console.ForegroundColor = ConsoleColor.Gray;
            bwait = false;
        }
        private static void StartSaving()
        {
            savingErrors = true;
            ErrorSaver.Start();
        }

        public static void WriteDCError(string logText)
        {
            DateTime _DTN = DateTime.Now;
            string Current = "Event occurred : " + _DTN.ToLongTimeString() + ":" + _DTN.Millisecond.ToString() + "\r\n";

            ErrorQueue.Append(Current + logText + "\r\n\r\n");
            CurrentWaitingMessages++;
            //if (CurrentWaitingMessages >= 10)
            //    WriteAllErrors();
            if (!savingErrors)
            {
                StartSaving();
            }
            WriteError("Errormessage has been added to queue");
        }
        internal static void WriteAllErrors()
        {
            Out.WriteLine("Starting checking errorqueue");
            string DataToSave;
            while (true)
            {
                if (ErrorQueue.Length > 0)
                {
                    DataToSave = ErrorQueue.ToString();
                    //Fail = false;
                    try
                    {
                        StreamWriter fileWriter = new StreamWriter(IO.workingDirectory + @"\Logs\Exceptions.log", true);
                        fileWriter.Write(DataToSave.ToString());
                        fileWriter.Close();
                    }
                    catch (Exception e)
                    {
                        Out.WriteLine(e.ToString());
                    }
                    Out.WriteLine("All errors where successfully saved.");
                    ErrorQueue = new StringBuilder();
                }
                Thread.Sleep(10000);
            }
        }
    }
}
