using System;
using System.Drawing;
using System.Windows.Forms;
using MVShareStore;

namespace MVConfigHandler.forms
{
	/// <summary>
	/// Create a new AddDataItem which can be used, as its name implies, to add new DataItems to DataPacks / DataShares / DataStores.
	/// </summary>
	public partial class AddDataItem : Form
	{
		/// <summary>
		/// Create a new AddDataItem Form which can be used, as its name implies, to add new DataItems to DataPacks / DataShares / DataStores.
		/// It can also be used to Edit / Modify and Insert Data Items.
		/// </summary>
		/// <param name="config">The MVConfigFile instance to add the Items to.</param>
		/// <param name="item">If a Data Item is supplied here then it will be displayed ready for editing / modifying</param>
		/// <param name="index">If an index value of 0 or higher is specified then that is the index used to insert it into the DataPack / DataShare / DataStore</param>
		public AddDataItem(MVConfigFile config, DataItem item = null, int index = -1) {
			InitializeComponent();

			if (config == null) config = new MVConfigFile();
			_config = config;
			ChangeToString(true);

			//	If a DataItem has been specified then we are expecting to edit it so put this form into Edit Mode.
			if (item != null) {
				_editMode = true;
				DataItem = item;
				AddBtn.Text = "Edit Item";
				StatusBar.Items[0].Text = this.Text = "Edit Data Item";
				ToolTip.SetToolTip(AddBtn, "Apply any edits to this Data Item in the Config File");
				_type = item.Type;
				TypeComboBox.Text = DataItem.Desc;
				NameBox.Text = DataItem.Name;

				if (_type == DataType.TYPE.STRING) {
					TextBox.Text = DataItem.AsStringValue;
				}
				else if(_type == DataType.TYPE.DATAPACK) {
					TextBox.Text = DataItem.AsStringValue;
				}
				else {
					ChangeToString(false);
					ValueBox.Text = DataItem.AsStringValue;
				}
			}
			else if(index > -1) {
				_insertMode = true;
				_index = index;
				AddBtn.Text = "Insert Item";
				setStatusBar(this.Text = "Insert New Data Item(s) at Index # " + index);
				ToolTip.SetToolTip(AddBtn, "Insert an additional Data Item to the Config File before the currently selected Data Item");
			}
		}

		/// <summary>
		/// The DataPack of Data Items that have been added using this form
		/// </summary>
		public DataPack DataItems { get; private set; } = new DataPack();

		/// <summary>
		/// The current Data Item (last added)
		/// </summary>
		public DataItem DataItem { get; private set; } = null;

		private string setStatusBar(string status) {
			if(status.Length < 90)
				return StatusBar.Items[0].Text = status;
			else
				return StatusBar.Items[0].Text = status.Substring(0, 90);
		}

		private void TypeComboBox_SelectedIndexChanged(object sender, EventArgs e) {
			ValueBox.Enabled = ValueBox.Visible = TextBox.Enabled = TextBox.Visible = true;
			NameLab.Text = "Enter a Name for this Config Entry (max 90 chars and no duplicates)";
			ValueBox.Text = ValueBox.Mask = "";
			AddBtn.Text = "Add Item";

			ChangeToString(false);
			if (TypeComboBox.Text.Equals("Section")) TypeComboBox.Text = "Datapack";
			_type = DataType.getDataType(TypeComboBox.Text);

			if (_type == DataType.TYPE.STRING) {
				setStatusBar(ValueLab.Text = "Enter a String value for this Config Entry (can be blank)");
				ChangeToString(true);
			}
			else if (_type == DataType.TYPE.BOOL) {
				ValueBox.Mask = "A????";
				setStatusBar(ValueLab.Text = "Enter a Boolean value for this Config Entry (T or F, True or False, 1 or 0)");
			}
			else if (_type == DataType.TYPE.INT) {
				ValueBox.Mask = "###########";
				setStatusBar(ValueLab.Text = "Enter an Int (signed 32 bit integer) value (-2,147,483,648 to 2,147,483,647)");
			}
			else if (_type == DataType.TYPE.DATAPACK) {
				setStatusBar(NameLab.Text = "Enter the name of the Section to create");
				ValueBox.Visible = TextBox.Visible = false;
				ValueLab.Text = "";
				AddBtn.Text = "Add Entries";
			}
			else {
				setStatusBar(ValueLab.Text = "Enter a String value for this Config Entry (can be blank)");
			}
		}

		private void TextBox_MouseHover(object sender, EventArgs e) {
			if ((_type == DataType.TYPE.STRING) && (!string.IsNullOrEmpty(TextBox.Text))) {
				ToolTip.SetToolTip(TextBox, TextBox.Text);
			}
		}

		private void AddDataItem_Resize(object sender, EventArgs e) {
			Size size = TextBox.Size;
			size.Width = this.Width - 75;
			size.Height = this.Height - 320;
			TextBox.Size = size;			
		}

		private void ChangeToString(bool toString) {
			Size size = this.Size;
			if (toString) {
				ValueBox.Visible = false; ValueBox.TabIndex = 99;
				TextBox.Visible = true; TextBox.TabIndex = 3;
				size.Height = 440;
				this.Size = size;
			}
			else {
				ValueBox.Visible = true; ValueBox.TabIndex = 3;
				TextBox.Visible = false; TextBox.TabIndex = 99;
				size.Height = 340;
				size.Width = 610;
				this.Size = size;
			}
		}

		private void AddBtn_Click(object sender, EventArgs e) {


			//	If we have a value for the Name then we need to check it has not been used before
			if (!_editMode) {
				if (!string.IsNullOrEmpty(NameBox.Text)) {
					if ((DataItems.Exists(NameBox.Text)) || (_config.entryExists(NameBox.Text))) {
						MessageBox.Show(setStatusBar(Data.LastError = "Duplicate Data Item Name " + NameBox.Text + " has been used before. Please specify another Name"), "Add New Data Item", MessageBoxButtons.OK, MessageBoxIcon.Error);
						NameBox.Focus();
						return;
					}
				}
			}

			//	We are in edit mode so we only need to check for duplicates if the name has changed
			else {
				if ((!string.IsNullOrEmpty(NameBox.Text)) && (!NameBox.Text.Equals(DataItem.Name))) {
					if ((DataItems.Exists(NameBox.Text)) || (_config.entryExists(NameBox.Text))) {
						MessageBox.Show(Data.LastError = "Duplicate Data Item Name " + NameBox.Text + " has been used before. Please specify another Name", "Edit Data Item", MessageBoxButtons.OK, MessageBoxIcon.Error);
						setStatusBar("Duplicate Data Item Name " + NameBox.Text + " has been used before. Please specify another Name");
						NameBox.Focus();
						return;
					}
				}
			}

			//	This is a Datapack type so we handle it completely differently
			if (_type == DataType.TYPE.DATAPACK) {
				DataPack dataPack = new DataPack();
				if(_editMode) dataPack = (DataPack)DataItem.Value;
				MVConfigFile config = new MVConfigFile(dataPack);

				//	Show the EditDataItems form to create a new DataPack
				forms.EditDataItems editDataPack = new forms.EditDataItems(config);
				DialogResult result = editDataPack.ShowDialog();
				if(result == DialogResult.OK) {
					dataPack = editDataPack.ConfigFile.getData();
					DataItem = DataItem.CreateDataItem(_type, dataPack, NameBox.Text, CodeBox.Text);
					DataItems.Add(DataItem);

					if (!string.IsNullOrEmpty(DataItem.Name))
						setStatusBar(DataItem.Desc + " Section " + DataItem.Name + " successfully added at Index " + (DataItems.ItemCount - 1) + ". Item Count = " + ((DataPack)DataItem.Value).ItemCount);
					else
						setStatusBar(DataItem.Desc + " Section successfully added at Index " + (DataItems.ItemCount - 1) + ". Item Count = " + ((DataPack)DataItem.Value).ItemCount);
				}

				NameBox.Focus();
				return;
			}

			//	Now verify that the value supplied seems to be valid 
			if ((_type != DataType.TYPE.STRING) && (!DataType.isValidValue(_type, ValueBox.Text))) {
				MessageBox.Show(Data.LastError = "The " + _type + " value specified does not appear to be a valid value for this Data Type. Please try again", "Add New Data Item", MessageBoxButtons.OK, MessageBoxIcon.Error);
				setStatusBar("The " + _type + " value specified does not appear to be a valid value for this Data Type. Please try again");
				ValueBox.Focus();
				return;
			}

			//	We are in Edit Mode so just change this DataItem and close with the expected result
			if (_editMode) {
				if (_type == DataType.TYPE.STRING)
					DataItem = DataItem.CreateDataItem(_type, TextBox.Text, NameBox.Text, CodeBox.Text);
				else
					DataItem = DataItem.CreateDataItem(_type, ValueBox.Text, NameBox.Text, CodeBox.Text);
				this.DialogResult = DialogResult.OK;
				Close();
			}

			//	We are in Insert Mode so keep checking and adding items
			else if (_insertMode) {
				try {
					if (_type == DataType.TYPE.STRING)
						DataItem = DataItem.CreateDataItem(_type, TextBox.Text, NameBox.Text, CodeBox.Text);
					else
						DataItem = DataItem.CreateDataItem(_type, ValueBox.Text, NameBox.Text, CodeBox.Text);

					DataItems.Add(DataItem);
					if (!string.IsNullOrEmpty(DataItem.Name))
						setStatusBar(DataItem.Desc + " Data Item " + DataItem.Name + " successfully inserted at Index " + (_index + (DataItems.ItemCount - 1)) + ". Value = " + DataItem.Value);
					else
						setStatusBar(DataItem.Desc + " Data Item successfully inserted at Index " + (_index + (DataItems.ItemCount - 1)) + ". Value = " + DataItem.Value);
					NameBox.Focus();
				}
				catch (Exception ex) {
					MessageBox.Show(setStatusBar(Data.LastError = "Unable to insert Data Item. Error: " + ex.Message), "Insert Data Item", MessageBoxButtons.OK, MessageBoxIcon.Error);
				}
			}

			//	We are not in Edit or Insert Mode and it all looks good so try and add it to the DataItems List.
			else {
				try {
					if (_type == DataType.TYPE.STRING)
						DataItem = DataItem.CreateDataItem(_type, TextBox.Text, NameBox.Text, CodeBox.Text);
					else
						DataItem = DataItem.CreateDataItem(_type, ValueBox.Text, NameBox.Text, CodeBox.Text);

					DataItems.Add(DataItem);
					if (!string.IsNullOrEmpty(DataItem.Name))
						setStatusBar(DataItem.Desc + " Data Item " + DataItem.Name + " successfully added at Index " + (DataItems.ItemCount - 1) + ". Value = " + DataItem.Value);
					else
						setStatusBar(DataItem.Desc + " Data Item successfully added at Index " + (DataItems.ItemCount - 1) + ". Value = " + DataItem.Value);
					NameBox.Focus();
				}
				catch (Exception ex) {
					MessageBox.Show(setStatusBar(Data.LastError = "Unable to add Data Item. Error: " + ex.Message), "Add Data Item", MessageBoxButtons.OK, MessageBoxIcon.Error);
				}
			}
		}

		private void CancelBtn_Click(object sender, EventArgs e) {
			Close();
		}

		private void CloseBtn_Click(object sender, EventArgs e) {
			Close();
		}

		private DataType.TYPE _type = DataType.TYPE.STRING;
		private MVConfigFile _config = null;
		private int _index = -1;
		private bool _insertMode = false;
		private bool _editMode = false;
	}
}
