using System;
using System.Threading;
using Plumtree.Remote.Logging;

/// <summary>
/// Demonstrates Plumtree EDK 5.2 logging API.
/// </summary>
public class LoggingCommandLineExample
{	
	private static readonly String INSTANCES_COMPONENT_NAME = "Instances";
	private static readonly String MAIN_LOOP_COMPONENT_NAME = "Main Loop";

	// characters legal for logging application names: ASCII alphanumerics and space plus . - and _.
	public static readonly String LOGGING_APPLICATION_NAME = "Logging_API_Example-1";

	// set to true to multicast log messages to local network
	// set to false to send message only listeners on local machine
	public static readonly bool LOG_TO_NETWORK = true;

	private ILogger logger;              // instance logging class
	private static ILogger mainLogger;   // main component logging class
	
	private Thread _thread;	             // thread for each instance of LoggingCommandLineExample

	// Suggested initialization for non-web applications is in a static block
	// in your application's main class or a logging utility class.
	static LoggingCommandLineExample()
	{
		// Don't attempt to re-initialize in case logging was already
		// initialized (for example, as part of an EDK-based web application).
		if (!LogFactory.IsInitialized())
		{
			LogFactory.Initialize(LOGGING_APPLICATION_NAME, LOG_TO_NETWORK);
		}
		
		Console.Out.WriteLine("Set your logging receiver to the \"server\" or \"application name\" ");
		Console.Out.WriteLine(LogFactory.GetApplicationName());
		Console.Out.WriteLine("The logging component names are \"EDK\", \"" + MAIN_LOOP_COMPONENT_NAME + "\" and \"" + INSTANCES_COMPONENT_NAME + "\".");
		
		mainLogger = LogFactory.GetLogger(MAIN_LOOP_COMPONENT_NAME, typeof(LoggingCommandLineExample));
	}	

	/// <summary>
	/// Constructor for LoggingCommandLineExample.
	/// </summary>
	/// <param name="instanceName"></param>
	public LoggingCommandLineExample(String instanceName)
	{
		_thread = new Thread(new ThreadStart(Run));
		_thread.Name = instanceName;
		this.logger = LogFactory.GetLogger(INSTANCES_COMPONENT_NAME, typeof(LoggingCommandLineExample));
		mainLogger.Info("Created new instance named {0}", instanceName);
	}				
	
	/// <summary>
	/// The main entry point for the logging example.
	/// </summary>
	[STAThread]
	public static void Main(string[] args)
	{
		String methodName = "main";
		mainLogger.FunctionBegin(methodName);

		// get a timestamp to measure performance of this function
		long performanceStartTicks = mainLogger.PerformanceBegin();

		mainLogger.Action("Creating and starting instances");

		LoggingCommandLineExample bill = new LoggingCommandLineExample("Bill");
		bill.Thread.Start();
		LoggingCommandLineExample larry = new LoggingCommandLineExample("Larry");
		larry.Thread.Start();

		mainLogger.Action("Done creating instances");

		// send log message with time since performanceBegin
		mainLogger.PerformanceEnd(methodName, performanceStartTicks);
		mainLogger.FunctionEnd(methodName);
	}
						

	/// <summary>
	/// Each thread runs through a small test of logging messages and
	/// interleaves work to the other by calling Thread.Sleep(1).
	/// </summary>
	private void Run()
	{
		String methodName = "run";

		// send log message that function is starting
		logger.FunctionBegin(methodName);

		// get a timestamp to measure performance of this function
		long performanceStartTicks = mainLogger.PerformanceBegin();

		Thread.Sleep(1);  // interleaves work to the other thread

		// demonstrates the available logging levels and shows use of token
		// substitution in format strings to construct messages.
		String levelDescriptionFormat = "{0} level messages are {1} by default in the log receiver.";

		// debug() through fatal() are increasingly serious warning messages.
		//   By comparison, the message types action, function, and performance
		//   are generally "info" or "debug" level, with Action perhaps representing
		//   a message more important than "Info".  Function and performance messages
		//   are off by default.
		logger.Debug(levelDescriptionFormat, "Debug", "off");
		logger.Info(levelDescriptionFormat, "Info",  "off");
		logger.Warn(levelDescriptionFormat, "Warn",  "on");
		logger.Error(levelDescriptionFormat, "Error", "on");
		logger.Fatal(levelDescriptionFormat, "Fatal", "on");

		Thread.Sleep(1);  // interleaves work to the other thread

		// Exceptions may also be caught and logged, and may use token substitution.
		try
		{
			throw new ThreadInterruptedException(_thread.Name + " was interrupted.");
		}
		catch (Exception eCaught)
		{
			logger.Warn(eCaught, "Caught an exception from {0}. ", eCaught.GetType().Name);
		}

		Thread.Sleep(1);  // interleaves work to the other thread

		// send log message with time since performanceBegin
		mainLogger.PerformanceEnd(methodName, performanceStartTicks);

		// send log message that function is ending
		logger.FunctionEnd(methodName);
	}


	/// <summary>
	/// Returns the thread for this instance.
	/// </summary>
	public Thread Thread
	{
		get 
		{ 
			return _thread; 
		}
	}

}
