using System;
using System.Windows.Forms;
using Microsoft.VisualBasic;
using MVShareStore;

namespace MVDataServer {

	/// <summary>
	/// Handle all the DataPack related functions: Create, Inquire, Modify, Remove.
	/// </summary>
	class DataPack 
	{
		/// <summary>
		/// Create a new DataPack and make it the current active DataPack
		/// </summary>
		/// <param name="main">The Main application form</param>
		/// <returns>True if a new DataPack was successfully created, otherwise false</returns>
		internal static bool CreateDataPack(Main main) {
			MVShareStore.DataPack dataPack = null;
			string result = null;

			try {
				if(MessageBox.Show("Do you want to populate the new DataPack with Data Items?", "Create new DataPack", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
					dataPack = Data.CreateDataPack(true);
				else
					dataPack = Data.CreateDataPack();

				if (dataPack == null) {
					if(main.showNotifications) MessageBox.Show("DataPack not created: " + Data.LastError, "Create New DataPack", MessageBoxButtons.OK);
					main.setStatusBar("DataPack not created: " + Data.LastError);
					return false;
				}
				else {
					if(dataPack.ItemCount == 0)
						result = "Successfully created new empty DataPack";
					else
						result = "Successfully created new DataPack containing " + dataPack.ItemCount + " Data Items";

					if(main.showNotifications) MessageBox.Show(result, "Create New DataPack", MessageBoxButtons.OK, MessageBoxIcon.Information);
					main.setStatusBar(result);
					return true;
				}
			}
			catch(Exception e) {
				if (main.showNotifications) MessageBox.Show("Error creating new DataPack: " + (Data.LastError = e.Message), "Create New DataPack", MessageBoxButtons.OK, MessageBoxIcon.Error);
				main.setStatusBar("Error creating new DataPack: " + (Data.LastError = e.Message));
				return false;
			}
		}

		/// <summary>
		/// Edit the Data Items in the currently active DataPack and return true if we were successful otherwise false
		/// </summary>
		/// <param name="main">The Main application form</param>
		/// <returns>True if the DataPack was successfully edited, otherwise false</returns>
		internal static bool EditDataPack(Main main) {
			try {
				//	We don't have a current Data Pack so create a new one instead?
				if(Data.CurrentDataPack == null) {
					if (MessageBox.Show(main.setStatusBar("No current Data Pack available. Do you want to create a new one?"), "Edit Data Pack", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
						return CreateDataPack(main);
					else {
						Data.LastError = "Unable to edit DataPack: No current Data Pack available";
						if (main.showNotifications) MessageBox.Show(main.setStatusBar(Data.LastError), "Edit DataPack", MessageBoxButtons.OK, MessageBoxIcon.Error);
						main.setStatusBar(Data.LastError);
						return false;
					}
				}

				Data.LastError = null;
				MVShareStore.DataPack dataPack = Data.EditDataPack();
				if(!string.IsNullOrEmpty(Data.LastError)) {
					if (main.showNotifications) MessageBox.Show(Data.LastError, "Edit Data Pack", MessageBoxButtons.OK, MessageBoxIcon.Information);
					main.setStatusBar(Data.LastError);
					return false;
				}

				if (main.showNotifications) MessageBox.Show("Successfully edited DataPack. Item count now = " + dataPack.ItemCount, "Edit Data Pack", MessageBoxButtons.OK, MessageBoxIcon.Information);
				main.setStatusBar("Successfully edited DataPack. Item count now = " + dataPack.ItemCount);
				return true;
			}
			catch(Exception e) {
				if (main.showNotifications) MessageBox.Show("Error editing DataPack: " + (Data.LastError = e.Message), "Edit Data Pack", MessageBoxButtons.OK, MessageBoxIcon.Error);
				main.setStatusBar(Data.LastError = "Error editing DataPack: " + (Data.LastError = e.Message));
				return false;
			}
		}

		/// <summary>
		/// List the contents of the currently active DataPack and return true if we were successful otherwise false
		/// </summary>
		/// <param name="main">The Main application form</param>
		/// <returns>True if the DataPack was successfully listed, otherwise false</returns>
		internal static bool ListDataPack(Main main) {
			try {
				if((Data.CurrentDataPack == null) || (Data.CurrentDataPack.ItemCount == 0)) {
					if (main.showNotifications) MessageBox.Show("No current DataPack or no Data Items to list in it", "List Data Pack", MessageBoxButtons.OK, MessageBoxIcon.Error);
					return false;
				}

				Data.ListDataPack();
				main.setStatusBar("Data Items in the currently active Data Pack listed");
				return true;
			}
			catch (Exception e) {
				if (main.showNotifications) MessageBox.Show("Error listing DataPack contents: " + (Data.LastError = e.Message), "List DataPack Items", MessageBoxButtons.OK, MessageBoxIcon.Error);
				main.setStatusBar(Data.LastError = "Error listing DataPack contents: " + (Data.LastError = e.Message));
				return false;
			}
		}

		/// <summary>
		/// Sort the contents of the currently active DataPack and return true if we were successful otherwise false
		/// </summary>
		/// <param name="main">The Main application form</param>
		/// <returns>True if the DataPack was successfully sorted, otherwise false</returns>
		internal static bool SortDataPack(Main main) {
			try {
				if ((Data.CurrentDataPack == null) || (Data.CurrentDataPack.ItemCount == 0)) {
					if (main.showNotifications) MessageBox.Show("No current DataPack or no Data Items to sort in it", "Sort Data Pack", MessageBoxButtons.OK, MessageBoxIcon.Error);
					return false;
				}

				bool descending = false;
				if (MessageBox.Show("Do you want to sort the Data Items into descending order?", "Sort Data Pack Items", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) descending = true;
				bool sortByCode = false;
				if (MessageBox.Show("Do you want to sort the Data Items by their Code Field first?", "Sort Data Pack Items", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) sortByCode = true;

				if (Data.SortDataPackItems(descending, sortByCode) == -1) {
					if (main.showNotifications) MessageBox.Show(Data.LastError, "Sort Data Pack Items", MessageBoxButtons.OK, MessageBoxIcon.Information);
					main.setStatusBar(Data.LastError);
					return false;
				}

				Data.ListDataPack();
				main.setStatusBar("Data Items in the currently active Data Pack sorted");
				return true;
			}
			catch (Exception e) {
				if (main.showNotifications) MessageBox.Show("Error sorting DataPack contents: " + (Data.LastError = e.Message), "Sort DataPack Items", MessageBoxButtons.OK, MessageBoxIcon.Error);
				main.setStatusBar(Data.LastError = "Error sorting DataPack contents: " + (Data.LastError = e.Message));
				return false;
			}
		}

		/// <summary>
		/// Merge the supplied DataPack / DataShare / DataStore with another DataPack / DataShare / DataStore or a new DataPack or a DataStore off disk opened as a DataPack
		/// </summary>
		/// <param name="main">The Main application form</param>
		/// <returns>True if the DataPack was successfully merged, otherwise false</returns>
		internal static bool MergeDataPack(Main main) {
			try {
				if ((Data.CurrentDataPack == null) || (Data.CurrentDataPack.ItemCount == 0)) {
					if (main.showNotifications) MessageBox.Show("No current DataPack or no Data Items to merge in it", "Merge Data Pack", MessageBoxButtons.OK, MessageBoxIcon.Error);
					return false;
				}

				//	TODO - This needs to be tested with a null DataPack and cancelled merge
				MVShareStore.DataPack dataPack = Data.CurrentDataPack;
				if ((dataPack = Data.ShowMergeDataItemsForm(Data.CurrentDataPack)) == null) {
					if (main.showNotifications) MessageBox.Show(Data.LastError, "Merge Data Pack Items", MessageBoxButtons.OK, MessageBoxIcon.Information);
					main.setStatusBar(Data.LastError);
					return false;
				}

				Data.CurrentDataPack = dataPack;
				main.setStatusBar("Data Items in the currently active Data Pack merged");
				return true;
			}
			catch (Exception e) {
				if (main.showNotifications) MessageBox.Show("Error merging DataPack Data Items: " + (Data.LastError = e.Message), "Merge DataPack Items", MessageBoxButtons.OK, MessageBoxIcon.Error);
				main.setStatusBar(Data.LastError = "Error merging DataPack Data Items: " + (Data.LastError = e.Message));
				return false;
			}
		}

		/// <summary>
		/// Extract a DataPack Data Item from the currently active DataPack optionally removing it in the process
		/// </summary>
		/// <param name="main">The Main application form</param>
		/// <returns>True if the Data Pack was found and displayed for editing, otherwise false</returns>
		internal static bool ExtractDataPack(Main main) {
			string name = null;
			bool remove = false;

			try {
				if ((Data.CurrentDataPack == null) || (Data.CurrentDataPack.ItemCount == 0)) {
					if (main.showNotifications) MessageBox.Show("No current DataPack or no Data Items to show in it", "Extract Data Pack", MessageBoxButtons.OK, MessageBoxIcon.Error);
					main.setStatusBar("No current DataPack or no Data Items to show in it");
					return false;
				}

				name = Interaction.InputBox("Enter the name of the DataPack Data Item you want to extract (nested DataPacks can be accessed using the path / character in the name)", "Enter DataPack Data Item Name", "");
				if (string.IsNullOrEmpty(name)) {
					if (main.showNotifications) MessageBox.Show("No DataPack Data Item name specified", "Extract Data Pack", MessageBoxButtons.OK, MessageBoxIcon.Error);
					return false;
				}

				DialogResult result = MessageBox.Show("Do you want to remove the DataPack Data Item after it has been extracted?", "Extract Data Pack", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
				if (result == DialogResult.Cancel) {
					if (main.showNotifications) MessageBox.Show("Extract of DataPack cancelled by user", "Extract Data Pack", MessageBoxButtons.OK, MessageBoxIcon.Error);
					main.setStatusBar(Data.LastError = "Extract of Data Pack cancelled by user");
					return false;
				}
				else if (result == DialogResult.Yes) remove = true;

				MVShareStore.DataPack dataPack = Data.ExtractDataPack(name, remove);
				if (dataPack == null) {
					if (main.showNotifications) MessageBox.Show("Unable to extract the DataPack Data Item " + name + " Error: " + Data.LastError, "Extract Data Pack", MessageBoxButtons.OK, MessageBoxIcon.Error);
					main.setStatusBar("Unable to extract the DataPack Data Item " + name + " Error: " + Data.LastError);
					return false;
				}

				MVShareStore.forms.EditDataItems editDataItems = new MVShareStore.forms.EditDataItems(dataPack);
				editDataItems.ShowDialog();
				//				Data.ShowEditDataItemsForm(dataPack);
				return true;
			}
			catch (Exception e) {
				if (main.showNotifications) MessageBox.Show("Error extracting DataPack Data Item: " + (Data.LastError = e.Message), "Extract Data Pack", MessageBoxButtons.OK, MessageBoxIcon.Error);
				main.setStatusBar(Data.LastError = "Error extracting DataPack Data Item: " + (Data.LastError = e.Message));
				return false;
			}
		}

		/// <summary>
		/// Find a Data Item in the DataPack using its Name or Index
		/// </summary>
		/// <param name="main">The Main application form</param>
		/// <param name="edit">Edit the Data Item after it has been found? (defaults to false)</param>
		/// <returns>True if the Data Item was found, otherwise false</returns>
		internal static bool FindDataItem(Main main, bool edit = false) {
			DataItem item = null;
			string indexname = null;
			int index = -1;

			try {
				if ((Data.CurrentDataPack == null) || (Data.CurrentDataPack.ItemCount == 0)) {
					if (main.showNotifications) MessageBox.Show("No current DataPack or no Data Items to show in it", "Find / Edit Data Item", MessageBoxButtons.OK, MessageBoxIcon.Error);
					return false;
				}

				DialogResult result = MessageBox.Show("Do you want to search for / find the Data Item by Name? Click Yes if you do otherwise No for using its Index instead", "Find / Edit Data Item", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
				if (result == DialogResult.Cancel) {
					if (main.showNotifications) MessageBox.Show("Find / Edit of Data Item cancelled by user", "Find / Edit Data Item", MessageBoxButtons.OK, MessageBoxIcon.Error);
					main.setStatusBar(Data.LastError = "Find / Edit of Data Item cancelled by user");
					return false;
				}
				else if (result == DialogResult.No) {
					indexname = Interaction.InputBox("Enter the index / position of the Data Item you want to find / edit", "Enter Data Item Index", "0");
					index++;
					if (int.TryParse(indexname, out index))
						item = Data.FindDataPackItem(index);
				}
				else if (result == DialogResult.Yes) {
					indexname = Interaction.InputBox("Enter the name of the Data Item you want to find / edit", "Enter Data Item Name", "");
					item = Data.FindDataPackItem(indexname);
				}

				if(item == null) {
					if (main.showNotifications) MessageBox.Show("Unable to find the Data Item " + indexname + " Error: " + Data.LastError, "Find / Edit Data Item", MessageBoxButtons.OK, MessageBoxIcon.Error);
					main.setStatusBar("Unable to find the Data Item " + indexname + " Error: " + Data.LastError);
					return false;
				}

				if (edit) {
					MVShareStore.forms.AddDataItem editDataItem = new MVShareStore.forms.AddDataItem(Data.CurrentDataPack, item);
					if (editDataItem.ShowDialog() == DialogResult.OK) {
						item = editDataItem.DataItem;
						if (index > -1) Data.CurrentDataPack.Edit(index, item);
						else
							Data.CurrentDataPack.Edit(indexname, item);
					}
				}

				if (main.showNotifications) MessageBox.Show("Data Item found / edited. Type = " + item.Type + " Name = " + item.Name + " Value = " + item.Value, "Find / Edit Data Item", MessageBoxButtons.OK, MessageBoxIcon.Error);
				main.setStatusBar("Data Item found / edited. Type = " + item.Type + " Name = " + item.Name + " Value = " + item.Value);
				return true;
			}
			catch (Exception e) {
				if (main.showNotifications) MessageBox.Show("Error finding / editing Data Item: " + (Data.LastError = e.Message), "Find / Edit Data Item", MessageBoxButtons.OK, MessageBoxIcon.Error);
				main.setStatusBar(Data.LastError = "Error finding / editing Data Item: " + (Data.LastError = e.Message));
				return false;
			}
		}

		/// <summary>
		/// Delete the currently active DataPack and remove it from memory (this will invalidate the current DataPack in the Data class)
		/// </summary>
		/// <param name="main">The Main application form</param>
		/// <returns>True if the DataPack was successfully deleted, otherwise false</returns>
		internal static bool DeleteDataPack(Main main) {
			try {	
				if (Data.CurrentDataPack == null) {
					if (main.showNotifications) MessageBox.Show("No currently active DataPack to delete", "Delete / close Data Pack", MessageBoxButtons.OK, MessageBoxIcon.Error);
					return false;
				}

				Data.CloseDataPack();
				if (main.showNotifications) MessageBox.Show("Currently active Data Pack now deleted / closed", "Delete / close DataPack", MessageBoxButtons.OK, MessageBoxIcon.Error);
				main.setStatusBar("Currently active Data Pack now deleted / closed");
				return true;
			}
			catch (Exception e) {
				if (main.showNotifications) MessageBox.Show("Error deleting DataPack: " + (Data.LastError = e.Message), "Delete / close DataPack", MessageBoxButtons.OK, MessageBoxIcon.Error);
				main.setStatusBar(Data.LastError = "Error deleting DataPack: " + (Data.LastError = e.Message));
				return false;
			}
		}

		/// <summary>
		/// Convert the currently active DataPack into a new DataShare
		/// </summary>
		/// <param name="main">The Main application form</param>
		/// <returns>True if the DataPack was successfully converted into a DataShare, otherwise false</returns>
		internal static bool ConvertDataPackToShare(Main main) {
			bool showDialog = false;

			try {
				if (MessageBox.Show("Do you want to enter additional information regarding the new DataShare?", "Convert to DataShare", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
					showDialog = true;

				if (Data.ConvertDataPackToDataShare(null, showDialog) == null) {
					if (main.showNotifications) MessageBox.Show("Error converting DataPack to a DataShare: " + Data.LastError, "Convert DataPack to DataShare", MessageBoxButtons.OK, MessageBoxIcon.Error);
					main.setStatusBar("Error converting DataPack to a DataShare: " + Data.LastError);
					return false;
				}

				if (main.showNotifications) MessageBox.Show("Currently active Data Pack now converted into a new Data Share " + Data.CurrentDataShare.Name, "Convert DataPack to DataShare", MessageBoxButtons.OK, MessageBoxIcon.Error);
				main.setStatusBar("Currently active Data Pack now converted into a new Data Share " + Data.CurrentDataShare.Name);
				return true;
			}
			catch (Exception e) {
				if (main.showNotifications) MessageBox.Show("Error converting DataPack to a DataShare: " + (Data.LastError = e.Message), "Convert DataPack to DataShare", MessageBoxButtons.OK, MessageBoxIcon.Error);
				main.setStatusBar(Data.LastError = "Error converting DataPack to a DataShare: " + (Data.LastError = e.Message));
				return false;
			}
		}

		/// <summary>
		/// Convert the currently active DataPack into a new DataStore
		/// </summary>
		/// <param name="main">The Main application form</param>
		/// <returns>True if the DataPack was successfully converted into a DataStore, otherwise false</returns>
		internal static bool ConvertDataPackToStore(Main main) {
			bool showDialog = false;

			try {
				if (MessageBox.Show("Do you want to enter additional information regarding the new DataStore?", "Convert to DataStore", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
					showDialog = true;

				if (Data.ConvertDataPackToDataStore(null, showDialog) == null) {
					if (main.showNotifications) MessageBox.Show("Error converting DataPack to a DataStore: " + Data.LastError, "Convert DataPack to DataStore", MessageBoxButtons.OK, MessageBoxIcon.Error);
					main.setStatusBar("Error converting DataPack to a DataStore: " + Data.LastError);
					return false;
				}

				if (main.showNotifications) MessageBox.Show("Currently active Data Pack now converted into a new Data Store " + Data.CurrentDataStore.Name, "Convert DataPack to DataStore", MessageBoxButtons.OK, MessageBoxIcon.Error);
				main.setStatusBar("Currently active Data Pack now converted into a new Data Store " + Data.CurrentDataStore.Name);
				return true;
			}
			catch (Exception e) {
				if (main.showNotifications) MessageBox.Show("Error converting DataPack to a DataStore: " + (Data.LastError = e.Message), "Convert DataPack to DataStore", MessageBoxButtons.OK, MessageBoxIcon.Error);
				main.setStatusBar(Data.LastError = "Error converting DataPack to a DataStore: " + (Data.LastError = e.Message));
				return false;
			}
		}

		/// <summary>
		/// Set the Code Field Header / Description to a value other than 'Code' to describe it's usage in this instance
		/// </summary>
		/// <param name="main">The Main application form</param>
		/// <returns>True if the DataPack Code Description was changed to a new value, otherwise false</returns>
		internal static bool SetDataPackCodeDescription(Main main) {
			try {
				if (Data.CurrentDataPack == null) {
					if (main.showNotifications) MessageBox.Show("No currently active DataPack to set code description for", "Set Code Field Description", MessageBoxButtons.OK, MessageBoxIcon.Error);
					return false;
				}

				string description = Interaction.InputBox("Enter the Header / Description of the Code Field in this DataPack", "Set Code Field Description", Data.CurrentDataPack.CodeDescription);
				if (!string.IsNullOrEmpty(description)) {
					Data.CurrentDataPack.CodeDescription = description;
					if (main.showNotifications) MessageBox.Show("Currently active Data Pack Code Field Description now set to " + Data.CurrentDataPack.CodeDescription, "Set Code Field Description", MessageBoxButtons.OK, MessageBoxIcon.Error);
					main.setStatusBar("Currently active Data Pack Code Field Description now set to " + Data.CurrentDataPack.CodeDescription);
					return true;
				}
				return false;
			}
			catch (Exception e) {
				if (main.showNotifications) MessageBox.Show("Error Setting DataPack Code Field Description: " + (Data.LastError = e.Message), "Set Code Field Description", MessageBoxButtons.OK, MessageBoxIcon.Error);
				main.setStatusBar(Data.LastError = "Error Setting DataPack Code Field Description: " + (Data.LastError = e.Message));
				return false;
			}
		}
	}
}
