using System;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
using System.Xml;
using System.Xml.Schema;
using System.IO;
using Orciid.Core.Util;

namespace Orciid.Core
{
	/// <summary>
	/// Interface between Orciid core and a relational database
	/// </summary>
	/// <remarks>
	/// This class is the base class for the different database connector classes.  Use the 
	/// <see cref="GetConnection()"/> method to retrieve a connector instance.
	/// </remarks>
	/// <example>
	/// Use the following construct to get a database connection.  Because of the <c>using</c>
	/// block, the connection will automatically be released once execution leaves the block.
	/// <code>
	/// using (DBConnection conn = DBConnector.GetConnection())
	/// {
	///		DataTable table = conn.SelectQuery("...");
	///		// process data
	/// }
	/// </code>
	/// </example>
	public class DBConnector
	{
		/// <summary>
		/// Requests a database connection object and opens the connection
		/// </summary>
		/// <remarks>
		/// This method returns an opened database connection object.
		/// For an example, see <see cref="DBConnector"/>.
		/// </remarks>
		/// <returns>an open database connection object for the server type being used</returns>
		public static DBConnection GetConnection()
		{
			return GetConnection(true);
		}

		/// <summary>
		/// Requests a database connection object
		/// </summary>
		/// <remarks>
		/// This method returns a database connection object.
		/// For an example, see <see cref="DBConnector"/>.
		/// </remarks>
		/// <param name="open"><c>true</c> if the connection should be opened automatically, <c>false</c> otherwise</param>
		/// <returns>a database connection object for the server type being used</returns>
		public static DBConnection GetConnection(bool open)
		{
			string servertype = Configuration.Instance.GetString("database.servertype");
			string connection = Configuration.Instance.GetString("database.connection");
			switch (servertype)
			{
				case ("MSSQL"):
					return new SQLServerDBConnection(connection, open);
				case ("MYSQL"):
					return new MySQLDBConnection(connection, open);
				default:
					throw new CoreException("Database type specified in configuration file not supported");
			}
		}

		internal static TraceSwitch dbTraceSwitch = new TraceSwitch("Database", "Database Activity");

		/// <summary>
		/// Set database activity trace level
		/// </summary>
		/// <remarks>
		/// With this method, the level of detail for the database activity trace log file can be set.
		/// </remarks>
		/// <param name="level">The level of detail to use for the trace log file.</param>
		public static void SetTraceLevel(TraceLevel level)
		{
			dbTraceSwitch.Level = level;
		}

		/// <summary>
		/// Initialize database connector class
		/// </summary>
		/// <remarks>
		/// Adds a configuration file change event handler to be notified when the configuration
		/// changes.
		/// </remarks>
		[Initialize]
		public static void Initialize()
		{
			Configuration.Instance.OnChange += new OnConfigurationChangeDelegate(Configuration_OnChange);
		}

		private static void Configuration_OnChange(IConfiguration configuration, object arg)
		{
			if (configuration.ContainsKey("database.trace") &&
				configuration.GetString("database.trace") == "on")
				SetTraceLevel(TraceLevel.Verbose);
			else
				SetTraceLevel(TraceLevel.Off);
		}
	}
}
