// Created with MonoDevelop
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2017 Thomas Klose & Torsten Schache, Hiperscan GmbH Dresden, Germany
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.


using System;
using Gtk;
using System.Security.Cryptography;
using System.Collections.Generic;
using System.Text;

using HollyLibrary;
using Hiperscan.Unix;
using Hiperscan.Extensions.ApoIdentCommon;
using System.IO;
using Hiperscan.FileIO;
using System.Linq;


namespace Hiperscan.Extensions.ApoIdent
{
	
	public partial class Preferences
	{
		#region methods	
		private void OnAddConfigButtonClicked(object o, EventArgs e)
		{
			string name = this.ShowConfigDialog(true);
			if (String.IsNullOrEmpty(name) == true)
				return;

			if (this.Config.Profiles.ContainsKey(name) == true)
			{
				Plugin.host.ShowInfoMessage(this.preferences_dialog,
				                                Catalog.GetString("A configuration profile with name \"{0}\" is already existing."),
				                                name);
				return;
			}

            Base64AddressDialog dialog = new Base64AddressDialog(this.preferences_dialog);
            ResponseType response = (ResponseType)dialog.Run();
            string license_block = dialog.LicenseBlock.Text;
            dialog.Destroy();

            if (response != ResponseType.Ok)
                return;

            string[] entries;
            try
            {
                entries = Base64AddressData.Decode(license_block);

                if (entries.Length < 6)
                    throw new Exception(Catalog.GetString("Unexpected license block entry count."));

                DateTime.Parse(entries[5], System.Globalization.CultureInfo.InvariantCulture);
            }
            catch (Exception ex) when (ex is ArgumentOutOfRangeException || ex is FormatException)
            {
                Plugin.host.ShowInfoMessage(this.preferences_dialog, Catalog.GetString("The license key is not valid. Please check your input."));
                Console.WriteLine("Cannot decrypt licence key: {0}", ex);                            
                return;
            }
            catch (Exception ex)
            {
                Plugin.host.ShowInfoMessage(this.preferences_dialog, Catalog.GetString("Cannot decode license block:") + " " + ex.Message);
                Console.WriteLine("Cannot decrypt licence key: {0}", ex);
                return;
            }
            
			this.Config.Profiles.Current = new Profile();
			this.Config.Profiles.Current.Name = name;

			this.Config.Profiles.Current.CustomerNumber = entries[0];
			this.Config.Profiles.Current.Company        = entries[1];
			this.Config.Profiles.Current.Street         = entries[2];
			this.Config.Profiles.Current.Town           = entries[3];
			this.Config.Profiles.Current.Archive        = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
                                                                    Plugin.name,
			                                                           Catalog.GetString("Archive"),
                                                                    FileIOHelper.ConvertToValidFilename(name));


			this.Config.Profiles.Current.Base64ConversionCreator   = entries[4];
			this.Config.Profiles.Current.Base64ConversionTimestamp = DateTime.Parse(entries[5], System.Globalization.CultureInfo.InvariantCulture);

			this.Config.Profiles.Current.FileNameStart = FilenameStartTypes.SubstanceName;

			if (this.Config.Profiles.IsDemoVersion == true)
            {
				this.Config.Profiles.IsDemoVersion = false;
                this.Config.Profiles.Clear();
            }

			this.Config.Profiles.Add(name, this.Config.Profiles.Current);

			this.Update(PreferencesUpdateStatus.ConfigSetAdded);
			this.customer_number_hregexentry.Entry.IsFocus = true;
		}

		private void OnRemoveConfigButtonClicked(object o, EventArgs e)
		{
			MessageDialog mdlg = new MessageDialog(this.preferences_dialog,
				DialogFlags.Modal,
				MessageType.Warning,
				ButtonsType.YesNo,
				Catalog.GetString("Are you sure, that you want to delete the profile '{0}'?"),
			                                       this.Config.Profiles.Current.Name);

            mdlg.IconList = ApoIdentStock.FinderIcons;
			ResponseType answer = (ResponseType) mdlg.Run();
			mdlg.Destroy();
            if (answer != ResponseType.Yes)
				return;

			this.Config.Profiles.Remove(this.Config.Profiles.Current.Name);
			if (this.Config.Profiles.Count > 0)
			{
				string new_name =  new List<string>(this.Config.Profiles.Keys)[0];
				this.Config.Profiles.Current = this.Config.Profiles[new_name];
			}
			else
			{
				this.Config.Profiles.Current = null;
			}

			this.Update(PreferencesUpdateStatus.ConfigSetRemoved);
		}

		private void OnRenameConfigButtonClicked(object o, EventArgs e)
		{
			string name = this.ShowConfigDialog(false);
			if (String.IsNullOrEmpty(name) == true || name == this.Config.Profiles.Current.Name)
				return;

			if (this.Config.Profiles.ContainsKey(name) == true)
			{
				Plugin.host.ShowInfoMessage(this.preferences_dialog,
					Catalog.GetString("A configuration profile with name \"{0}\" is already existing."),
					name);
				return;
			}

			string old_name = this.Config.Profiles.Current.Name;

			Profile profile = this.Config.Profiles.Current;
			this.Config.Profiles.Remove(old_name);
			profile.Name = name;
			this.Config.Profiles.Add(name, profile);

			this.Update(PreferencesUpdateStatus.ConfigSetRenamed);
			this.customer_number_hregexentry.Entry.IsFocus 	= true;
		}

		private string ShowConfigDialog(bool new_config)
		{
			string title = Catalog.GetString("New Configuration");
			if (new_config == false)
				title = Catalog.GetString("Rename Configuration");
			
			Dialog dialog = new Dialog(title,
				this.preferences_dialog,
				DialogFlags.Modal,
				Stock.Ok,     ResponseType.Ok,
				Stock.Cancel, ResponseType.Cancel);

			dialog.Default = dialog.ActionArea.Children[1];

            Gtk.Label label = new Gtk.Label(Catalog.GetString("Enter configuration profile name:"));
			Entry entry = new Entry(Catalog.GetString("New profile"));
			if (new_config == false)
				entry.Text = this.Config.Profiles.Current.Name;
			
			entry.SelectRegion(0, entry.Text.Length - 1);
			entry.ActivatesDefault = true;
			HBox hbox = new HBox();
			hbox.Spacing = 10;

			hbox.PackStart(label, false, false, 0);
			hbox.PackStart(entry, false, false, 0);

			Alignment align 	= new Alignment(0f, 0f, 0f, 0f);
			align.LeftPadding 	= 20;
			align.RightPadding 	= 5;
			align.TopPadding 	= 5;
			align.BottomPadding = 5;
			align.Add(hbox);
			dialog.VBox.PackStart(align);
			dialog.ShowAll();

            dialog.IconList = ApoIdentStock.FinderIcons;
			ResponseType choice = (ResponseType)dialog.Run();
			string name = StringHelper.CleanUserInputString(entry.Text.Trim());
			dialog.Destroy();

			if (choice != ResponseType.Ok)
				name = String.Empty;

			return name;
		}

		
		private void CheckDirectoryEntriesForDoubleEntries()
		{
			if (this.Config.Profiles.Current == null)
				return;
			
			Dictionary<string, List<string>> messages = new Dictionary<string,List<string>>();
			foreach (Profile profile1 in this.Config.Profiles.Values)
			{
				if (profile1.IgnoreMissingArchive == true)
					continue;
				
				foreach (Profile profile2 in this.Config.Profiles.Values)
				{
					if (profile1.Name == profile2.Name)
						continue;

					if (profile2.IgnoreMissingArchive == true)
						continue;
					
					if(messages.ContainsKey(profile1.Archive))
						continue;

					if (profile1.Archive == profile2.Archive)
					{
						List<string> users = new List<string>();
						foreach (Profile profile3 in this.Config.Profiles.Values)
						{
							if (profile1.Archive == profile3.Archive)
							{
								if (users.Contains(profile3.Name) == false)
									users.Add(profile3.Name);
							}
						}
						messages.Add(profile1.Archive, users);	
						break;
					}
				}
			}
			if(messages.Count > 0)
			{
				StringBuilder output = new StringBuilder();
				output.Append(Catalog.GetString("One of the archive directories is used by more than one configuration profile. " +
				                                "This is not recommended and is known to cause problems in archive query. " +
				                                "The following list shows possible conflicts:"));
				output.AppendLine();
				foreach (KeyValuePair<string, List<string>> item in messages) 
				{
					output.AppendLine();
					output.AppendLine(string.Format(Catalog.GetString("Archive \"{0}\" is used by:"), item.Key));
					foreach (string user in item.Value)
					{
						output.AppendLine("    -" + user);
					}
				}
				Plugin.host.ShowInfoMessage(this.preferences_dialog,output.ToString());
			}
		}

        public static void CheckForDemoVersion(Gtk.Window parent, Configurations config)
        {
			if (config.Profiles.IsDemoVersion == true)
            {
                MessageDialog dialog = new MessageDialog(parent, DialogFlags.Modal, MessageType.Warning, ButtonsType.Ok, true,
                                                         Catalog.GetString("<b>The address data aren't valid!</b>\n" +
                                                                           "The current profile can be used only for demo purposes. " +
                                                                           "NIR protocols created with this profile aren't valid. " +
                                                                           "In order to create a new profile, please click the <b>+</b>\u00A0symbol in the preferences dialog.\n\n" +
                                                                           "You can find the license key either in your Apo-Ident folder on the desktop or in another selected archive folder.\n\n"));

                dialog.Title = Catalog.GetString("Invalid Address Data");
                dialog.IconList = ApoIdentStock.FinderIcons;
                dialog.Run();
                dialog.Destroy();
            }
        }

		private void OnShowInfoLinkbuttonClicked(object sender, EventArgs e)
		{
			Gtk.LinkButton linkbutton = sender as LinkButton;
			if(linkbutton != null)
			{
				MessageKeys key = MessageKeys.None;
				switch(linkbutton.Name)
				{
				case "lennartz_linkbutton": 
					key = MessageKeys.Lennartz;
					break;
				case "show_difference_linkbutton": 
					key = MessageKeys.ShowDifference;
					break;

				default: 
					break;
				}

				MessageObject long_info_object = MessageCatalog.GetMessageByID(key);
				HToolTip.ShowToolTipAsDialog(linkbutton,
				                                long_info_object.Title,
				                    			long_info_object.Message,			           
				                             	Stock.DialogInfo);
				linkbutton.Label ="?";
			}
		}
		#endregion
	}
}