﻿using System;
using System.Linq;
using System.Runtime.CompilerServices;
using System.IO;
using System.Reflection;

namespace LogSharp
{
	public enum LogLevel {
		Verbose,
		Info,
		Debug,
		Warning,
		Error
	}

	public class Log
	{
		/// Display log or not
		public static bool output = false;
		/// Display Separator or not
		public static bool useSeparator = false;
		/// Separator String if you use Separator
		public static string separator = "----------------------------------------";
		/// Display Log Level or not
		public static bool useLogLevel = true;
		/// Display DateTime or not
		public static bool useDateTime = true;
		/// Display Class Name or not
		public static bool useClassName = true;
		/// Display Function Name or not
		public static bool useFunction = true;
		/// Display Verbose log or not
		public static bool showVerbose = true;
		/// Display Info log or not
		public static bool showInfo = true;
		/// Display Debug log or not
		public static bool showDebug = true;
		/// Display Warning log or not
		public static bool showWarning = true;
		/// Display Error log or not
		public static bool showError = true;

		public static void Verbose(object obj = null, [CallerMemberName] string member = "", [CallerFilePath] string filepath = "", [CallerLineNumber] int line = 0)
		{
			ToFormatString(LogLevel.Verbose, obj, member, filepath, line);
		}

		public static void Info(object obj = null, [CallerMemberName] string member = "", [CallerFilePath] string filepath = "", [CallerLineNumber] int line = 0)
		{
			ToFormatString(LogLevel.Info, obj, member, filepath, line);
		}

		public static void Debug(object obj = null, [CallerMemberName] string member = "", [CallerFilePath] string filepath = "", [CallerLineNumber] int line = 0)
		{
			ToFormatString(LogLevel.Debug, obj, member, filepath, line);
		}

		public static void Warning(object obj = null, [CallerMemberName] string member = "", [CallerFilePath] string filepath = "", [CallerLineNumber] int line = 0)
		{
			ToFormatString(LogLevel.Warning, obj, member, filepath, line);
		}

		public static void Error(object obj = null, [CallerMemberName] string member = "", [CallerFilePath] string filepath = "", [CallerLineNumber] int line = 0)
		{
			ToFormatString(LogLevel.Error, obj, member, filepath, line);
		}

		private static void ToFormatString(LogLevel LogLevel, object obj = null, string member = "", string filepath = "", int line = 0)
		{
			if (!output) return;
			
			var log = "";
			var level = useLogLevel ? string.Format("[{0}] ", LogLevel) : "";
			var time = useDateTime ? string.Format("{0} ", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")) : "";
			var className = useClassName ? string.Format("[{0}:{1}] ", Path.GetFileNameWithoutExtension(filepath).Split('\\').LastOrDefault(), line) : "";
			var functionName = useFunction ? member : "";

			log += level + time + className + functionName;

			if (obj == null)
			{
				log += "";
			}
			else if (obj is string)
			{
				log += string.Format("\n\"{0}\"", obj);
			}
			else {
				log += string.Format("\n{0}", obj);
			}

			if (useSeparator) {
				log += "\n" + separator;
			}

			System.Diagnostics.Debug.WriteLine(log);
		}

		public static void description()
		{
			if (!output) return;
			
			var assembly = typeof(LogSharp.Log).GetTypeInfo().Assembly;
			var version = assembly.GetName().Version;

			System.Diagnostics.Debug.WriteLine(string.Format("[Log] version: {0}", version));
			System.Diagnostics.Debug.WriteLine(string.Format("\tUSE_SEPARATOR: {0}", useSeparator));
			System.Diagnostics.Debug.WriteLine(string.Format("\tSEPARATOR_STRING: {0}", separator));
			System.Diagnostics.Debug.WriteLine(string.Format("\tUSE_LOG_LEVEL: {0}", useLogLevel));
			System.Diagnostics.Debug.WriteLine(string.Format("\tUSE_DATETIME: {0}", useDateTime));
			System.Diagnostics.Debug.WriteLine(string.Format("\tUSE_CLASS_NAME: {0}", useClassName));
			System.Diagnostics.Debug.WriteLine(string.Format("\tUSE_FUNCTION_NAME: {0}", useFunction));
			System.Diagnostics.Debug.WriteLine(string.Format("\tSHOW_VERBOSE: {0}", showVerbose));
			System.Diagnostics.Debug.WriteLine(string.Format("\tSHOW_INFO: {0}", showInfo));
			System.Diagnostics.Debug.WriteLine(string.Format("\tSHOW_DEBUG: {0}", showDebug));
			System.Diagnostics.Debug.WriteLine(string.Format("\tSHOW_WARNING: {0}", showWarning));
			System.Diagnostics.Debug.WriteLine(string.Format("\tSHOW_ERROR: {0}", showError));
		}
	}
}

