using System;
using System.ComponentModel;
using System.Data.AccessClient;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using Medivators.Common;
using Medivators.Common.Enums;
using Medivators.Common.Logging;
using Medivators.Common.Settings;
using Infragistics.Win.UltraWinTabControl;

namespace Medivators.Reporting
{
	public partial class frmAdmin : frmBase
	{
		private bool _rebootNeeded = false;

		#region construct/load/dispose/close

		public frmAdmin()
		{
			InitializeComponent();
			//	no sense in allowing the button that opens
			//	this form to be used
			btnAdmin.BackColor = Color.Black;
			btnAdmin.BackColorLight = Color.Green;
			btnAdmin.Enabled = false;
			textAdmin.Enabled = false;
		}

		protected override void form_Load(object sender, EventArgs e)
		{
			try
			{
				base.form_Load(sender, e);
				LoadTextBoxes();
				LoadCheckBoxes();
				LoadCombos();
				_dirty = false;
			}
			catch (Exception ex)
			{
				using (dlgError dlg = new dlgError())
				{
					dlg.Message = "Error encountered while loading Cycles form";
					dlg.Details = ex.ToString();
					dlg.ShowDialog();
				}
			}
		}

		#region * private load helpers

		private void LoadTextBoxes()
		{
			textCommitGranularity.Text = TextSettings.GetInstance()[SettingTypes.Application, "CommitGranularity"];
			textCommitInterval.Text = TextSettings.GetInstance()[SettingTypes.Application, "CommitInterval"];
			textParseInterval.Text = TextSettings.GetInstance()[SettingTypes.Application, "ParseInterval"];
			// DB Path one has to be parsed out of the connect string
			string[] elements = TextSettings.GetInstance()[SettingTypes.Application, "DataSource"].Split(";".ToCharArray());
			foreach (string el in elements)
			    if (el.ToLower().Trim().StartsWith("data source"))
				{
					string[] nameVal = el.Split("=".ToCharArray());
					if (nameVal.Length > 0)
						this.textDBPath.Text = nameVal[1].Trim().Replace(Constants.DoubleQuote, string.Empty);
					break;
				}
		}
		private void LoadCheckBoxes()
		{
			string[] ports = TextSettings.GetInstance()[SettingTypes.Application, "ActiveCommPorts"].Split(",".ToCharArray());
			foreach (string port in ports)
			{
				if (!port.Trim().Equals(string.Empty))
					switch ((CommPorts)System.Enum.Parse(typeof(Medivators.Common.Enums.CommPorts), port))
					{
						case CommPorts.COM1:
							checkComm1.Checked = true;
							break;
						case CommPorts.COM2:
							checkComm2.Checked = true;
							break;
						case CommPorts.COM3:
							checkComm3.Checked = true;
							break;
						case CommPorts.COM4:
							checkComm4.Checked = true;
							break;
						case CommPorts.COM5:
							checkComm5.Checked = true;
							break;
						case CommPorts.COM6:
							checkComm6.Checked = true;
							break;
						case CommPorts.COM7:
							checkComm7.Checked = true;
							break;
						case CommPorts.COM8:
							checkComm8.Checked = true;
							break;
                        case CommPorts.COM9:
                            checkComm9.Checked = true;
                            break;
                        case CommPorts.COM10:
                            checkComm10.Checked = true;
                            break;
                        case CommPorts.COM11:
                            checkComm11.Checked = true;
                            break;
                        case CommPorts.COM12:
                            checkComm12.Checked = true;
                            break;
                        case CommPorts.COM13:
                            checkComm13.Checked = true;
                            break;
                        case CommPorts.COM14:
                            checkComm14.Checked = true;
                            break;
                        case CommPorts.COM15:
                            checkComm15.Checked = true;
                            break;
                        case CommPorts.COM16:
                            checkComm16.Checked = true;
                            break;
                        case CommPorts.COM17:
                            checkComm17.Checked = true;
                            break;
                        case CommPorts.COM18:
                            checkComm18.Checked = true;
                            break;
                        case CommPorts.COM19:
                            checkComm19.Checked = true;
                            break;
                        case CommPorts.COM20:
                            checkComm20.Checked = true;
                            break;
                    }
			}
		}
		private void LoadCombos()
		{
			cboLogging.DataSource = System.Enum.GetNames(typeof(Medivators.Common.Enums.LoggingLevels));
			string wrk = TextSettings.GetInstance()[SettingTypes.Application, "LoggingLevel"];
			if ( ! wrk.Equals(string.Empty) )
				cboLogging.Value = Enum.Parse(typeof(LoggingLevels), wrk).ToString();

			//	for the rest, we need a CommPortSettings object
			string setStr = TextSettings.GetInstance()[SettingTypes.Application, "COMSettings"];
			CommPortSettings set = new CommPortSettings();
			set.FromString(setStr);

			cboBaudRate.DataSource = System.Enum.GetNames(typeof(Medivators.Common.Enums.BaudRates));
			cboBaudRate.Value = set.BaudRate.ToString();

			//cboDataBits
			cboDataBits.DataSource = System.Enum.GetNames(typeof(Medivators.Common.Enums.DataBits));
			cboDataBits.Value = set.DataBit.ToString();

			//cboHandShake
			cboHandShake.DataSource = System.Enum.GetNames(typeof(Medivators.Common.Enums.HandShakes));
			cboHandShake.Value = set.HandShake.ToString();

			//cboParity
			cboParity.DataSource = System.Enum.GetNames(typeof(Medivators.Common.Enums.Parities));
			cboParity.Value = set.Parity.ToString();

			//cboStopBit
			cboStopBit.DataSource = System.Enum.GetNames(typeof(Medivators.Common.Enums.StopBits));
			cboStopBit.Value = set.StopBit.ToString();
		}
		#endregion

		#endregion

		public override Enums.Forms FormType
		{
			get { return Enums.Forms.Admin; }
		}

		#region control events and change tracking

		#region *	changing any control value sets Dirty

		protected bool Dirty
		{
			get { return _dirty; }
			set
			{
				if (_dirty != value)
				{
					_dirty = value;
					cmdOK.Enabled = value;
				}
			}
		}
		private void Setting_Changed(object sender, EventArgs e)
		{
			Dirty = true;
			RebootCheck(sender);
		}
		#endregion

		#region *	changing all but one control means a reboot is needed

		private void RebootCheck(object sender)
		{
			if (!((Control)sender).Name.Equals(cboLogging.Name))
				_rebootNeeded = true;
		}

		#endregion

		private void btnBrowse_Click(object sender, EventArgs e)
		{
			if (textDBPath.Text != null)
				if (textDBPath.Text.Length > 0)
					if (File.Exists(textDBPath.Text))
						dlgOpenFile.FileName = textDBPath.Text;
			if (dlgOpenFile.ShowDialog() == DialogResult.OK)
				if (dlgOpenFile.FileName != null)
					if (dlgOpenFile.FileName.Length > 0)
						textDBPath.Text = dlgOpenFile.FileName;
		}

		#endregion

		#region command buttons

		private void cmdCancel_Click(object sender, EventArgs e)
		{
			this.Close();
		}
		private void cmdOK_Click(object sender, EventArgs e)
		{
			if (_dirty)
				if (ValidateSettings())
					Save();
		}

		#endregion

		#region save settings

		private bool ValidateSettings()
		{
			string msg = string.Empty;
			Control ctl = null;
			int tab = 0;

			#region **	numeric textboxes

			try
			{
				if (Convert.ToInt32(this.textCommitGranularity.Text) <= 0)
				{
					msg = "CommitGranularity must be a valid number greater than zero.";
					ctl = this.textCommitGranularity;
					tab = 1;
				}
			}
			catch
			{
				msg = "CommitGranularity must be a valid number greater than zero.";
				ctl = this.textCommitGranularity;
				tab = 1;
			}
			try
			{
				if (Convert.ToInt32(this.textCommitInterval.Text) <= 0)
				{
					msg = "CommitInterval must be a valid number greater than zero.";
					ctl = this.textCommitInterval;
					tab = 1;
				}
			}
			catch
			{
				msg = "CommitInterval must be a valid number greater than zero.";
				ctl = this.textCommitInterval;
				tab = 1;
			}
			try
			{
				if (Convert.ToInt32(this.textParseInterval.Text) <= 0)
				{
					msg = "ParseInterval must be a valid number greater than zero.";
					ctl = this.textParseInterval;
					tab = 1;
				}
			}
			catch
			{
				msg = "ParseInterval must be a valid number greater than zero.";
				ctl = this.textParseInterval;
				tab = 1;
			}

			#endregion

			#region ** password
			if ((this.txtNewPwd1.Text != null && this.txtNewPwd1.Text.Length > 0) ||
				(this.txtNewPwd2.Text != null && this.txtNewPwd2.Text.Length > 0))
			{
				pwd.VerifyResult result = pwd.ValidateChange(this.txtCurrentPwd.Text,
						this.txtNewPwd1.Text,
						this.txtNewPwd2.Text);
				switch (result)
				{
					case pwd.VerifyResult.Exception:
						msg = "Password must be at least six and at most 10 characters. Current password must be valid. New password and confirming password must match";
						ctl = this.txtCurrentPwd;
						tab = 4;
						break;
					case pwd.VerifyResult.Invalid:
						msg = "Current password must be valid";
						ctl = this.txtCurrentPwd;
						tab = 4;
						break;
					case pwd.VerifyResult.InvalidConfirmation:
						msg = "New password and confirming password must match";
						ctl = this.txtCurrentPwd;
						tab = 4;
						break;
					case pwd.VerifyResult.Malformed:
						msg = "Password must be at least six and at most 10 characters";
						ctl = this.txtCurrentPwd;
						tab = 4;
						break;
				}
			}
			#endregion

			// database
			if (!System.IO.File.Exists(this.textDBPath.Text))
			{
				msg = string.Format("Database file does not exist at path ({0})", this.textDBPath);
				ctl = textDBPath;
				tab = 0;
			}

			//	must be at least one active comm port
			if (!(checkComm1.Checked ||
				checkComm2.Checked ||
				checkComm3.Checked ||
				checkComm4.Checked ||
				checkComm5.Checked ||
				checkComm6.Checked ||
				checkComm7.Checked ||
				checkComm8.Checked ||
                checkComm9.Checked ||
				checkComm10.Checked ||
				checkComm11.Checked ||
				checkComm12.Checked ||
				checkComm13.Checked ||
				checkComm14.Checked ||
				checkComm15.Checked ||
                checkComm16.Checked ||
				checkComm17.Checked ||
				checkComm18.Checked ||
				checkComm19.Checked ||
				checkComm20.Checked ))
			{
				msg = string.Format("Please insure that at least one Comm Port is Active", this.textDBPath);
				ctl = checkComm1;
				tab = 2;
			}

			if (msg != string.Empty)
			{
				MsgBox.Show(msg, "Administration", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				tabs.SelectedTab = tabs.Tabs[tab];
				ctl.Focus();
				return false;
			}
			else
				return true;
		}
		protected override bool Save()
		{
			bool rtnVal = true;
			try
			{
				TextSettings.GetInstance()[SettingTypes.Application, "CommitGranularity"] = textCommitGranularity.Text;
				TextSettings.GetInstance()[SettingTypes.Application, "CommitInterval"] = textCommitInterval.Text;
				TextSettings.GetInstance()[SettingTypes.Application, "ParseInterval"] = textParseInterval.Text;

				TextSettings.GetInstance()[SettingTypes.Application, "LoggingLevel"] = (string)cboLogging.Value;
				string portsettings = string.Empty;

				TextSettings.GetInstance()[SettingTypes.Application, "DataSource"] = GetConnectString(this.textDBPath.Text);

				//BaudRate = bps4800{|}DataBit = Eight{|}Parity = None{|}StopBit = One{|}HandShake = CtsRts*
				portsettings += "BaudRate" + Constants.ValueDelimiter + (string)cboBaudRate.Value + Constants.StringDelimiter;
				portsettings += "DataBit" + Constants.ValueDelimiter + (string)cboDataBits.Value + Constants.StringDelimiter;
				portsettings += "Parity" + Constants.ValueDelimiter + (string)cboParity.Value + Constants.StringDelimiter;
				portsettings += "StopBit" + Constants.ValueDelimiter + (string)cboStopBit.Value + Constants.StringDelimiter;
				portsettings += "HandShake" + Constants.ValueDelimiter + (string)cboHandShake.Value;
				TextSettings.GetInstance()[SettingTypes.Application, "COMSettings"] = portsettings;
                //TextSettings.GetInstance()[SettingTypes.Application, "COM2Settings"] = portsettings;
                //TextSettings.GetInstance()[SettingTypes.Application, "COM3Settings"] = portsettings;
                //TextSettings.GetInstance()[SettingTypes.Application, "COM4Settings"] = portsettings;
                //TextSettings.GetInstance()[SettingTypes.Application, "COM5Settings"] = portsettings;
                //TextSettings.GetInstance()[SettingTypes.Application, "COM6Settings"] = portsettings;
                //TextSettings.GetInstance()[SettingTypes.Application, "COM7Settings"] = portsettings;
                //TextSettings.GetInstance()[SettingTypes.Application, "COM8Settings"] = portsettings;

				string ports = string.Empty;
				if (checkComm1.Checked) ports += CommPorts.COM1.ToString() + Constants.ElementDelimiter;
				if (checkComm2.Checked) ports += CommPorts.COM2.ToString() + Constants.ElementDelimiter;
				if (checkComm3.Checked) ports += CommPorts.COM3.ToString() + Constants.ElementDelimiter;
				if (checkComm4.Checked) ports += CommPorts.COM4.ToString() + Constants.ElementDelimiter;
				if (checkComm5.Checked) ports += CommPorts.COM5.ToString() + Constants.ElementDelimiter;
				if (checkComm6.Checked) ports += CommPorts.COM6.ToString() + Constants.ElementDelimiter;
				if (checkComm7.Checked) ports += CommPorts.COM7.ToString() + Constants.ElementDelimiter;
				if (checkComm8.Checked) ports += CommPorts.COM8.ToString() + Constants.ElementDelimiter;
                if (checkComm9.Checked) ports += CommPorts.COM9.ToString() + Constants.ElementDelimiter;
                if (checkComm10.Checked) ports += CommPorts.COM10.ToString() + Constants.ElementDelimiter;
                if (checkComm11.Checked) ports += CommPorts.COM11.ToString() + Constants.ElementDelimiter;
                if (checkComm12.Checked) ports += CommPorts.COM12.ToString() + Constants.ElementDelimiter;
                if (checkComm13.Checked) ports += CommPorts.COM13.ToString() + Constants.ElementDelimiter;
                if (checkComm14.Checked) ports += CommPorts.COM14.ToString() + Constants.ElementDelimiter;
                if (checkComm15.Checked) ports += CommPorts.COM15.ToString() + Constants.ElementDelimiter;
                if (checkComm16.Checked) ports += CommPorts.COM16.ToString() + Constants.ElementDelimiter;
                if (checkComm17.Checked) ports += CommPorts.COM17.ToString() + Constants.ElementDelimiter;
                if (checkComm18.Checked) ports += CommPorts.COM18.ToString() + Constants.ElementDelimiter;
                if (checkComm19.Checked) ports += CommPorts.COM19.ToString() + Constants.ElementDelimiter;
                if (checkComm20.Checked) ports += CommPorts.COM20.ToString() + Constants.ElementDelimiter;
                if (ports.EndsWith(Constants.ElementDelimiter))
					ports = ports.Substring(0, ports.Length - 1);
				TextSettings.GetInstance()[SettingTypes.Application, "ActiveCommPorts"] = ports;

				#region ** password
				
				if (this.txtNewPwd1.Text != null ||
					this.txtNewPwd1.Text.Length > 0 ||
					this.txtNewPwd2.Text.Length > 0)
					pwd.Set(this.txtCurrentPwd.Text,
						this.txtNewPwd1.Text,
						this.txtNewPwd2.Text);

				#endregion

				if (_rebootNeeded)
					MsgBox.Show("Changes will not affect the Medivators.Listener until the next reboot",
								"Settings Changed",
								MessageBoxButtons.OK,
								MessageBoxIcon.Exclamation);
				_rebootNeeded = false;

				TextSettings.GetInstance().Save();

				Dirty = false;
			}
			catch (Exception ex)
			{
				using (dlgError dlg = new dlgError())
				{
					dlg.Message = "An error was encountered while saving. Changes may not have saved.";
					dlg.Details = ex.ToString();
					dlg.ShowDialog();
				}
			}
			return rtnVal;
		}

		#endregion

		#region test connection

		private string GetConnectString(string DBPath)
		{
			return "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\"" + DBPath + "\";Persist Security Info=True";
		}
		private bool TestConnection(string DBPath)
		{
			bool rtnVal = true;
			try
			{
				AccessConnection cnn = new AccessConnection();
				cnn.ConnectionString = GetConnectString(DBPath);
				cnn.Open();
				cnn.Close();
				cnn.Dispose();
				
			}
			catch (Exception ex)
			{
				using (dlgError dlg = new dlgError())
				{
					dlg.Message = string.Format("Unable to connect to database ({0}).", DBPath);
					dlg.Details = ex.ToString();
					dlg.ShowDialog();
				}
				rtnVal = false;
			}
			return rtnVal;
		}
		private void btnTestConnection_Click(object sender, EventArgs e)
		{
			if ( TestConnection(this.textDBPath.Text))
				MsgBox.Show("Successful Connection!", "Connection Test", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
		}

		#endregion

		private void cmdTools_Click(object sender, EventArgs e)
		{
			using (dlgDatabaseTools dlg = new dlgDatabaseTools())
			{
				dlg.DatabasePath = this.textDBPath.Text;
				dlg.ShowDialog();
			}
		}

	}
}