// 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 System.Collections.Generic;
using System.IO;
using System.Text;

using Gtk;

using Hiperscan.Common.IO;
using Hiperscan.Unix;
using Hiperscan.GtkExtensions.Widgets;
using Hiperscan.Extensions.ApoIdentCommon;

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.AllProfiles.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 Configurations.ProfilePreferences();
            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 = Configurations.FilenameStartTypes.SubstanceName;

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

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

            this.Update(PreferencesUpdateStatus.ConfigSetAdded);
            this.customer_number_regexentry.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.AllProfiles.Remove(this.Config.Profiles.Current.Name);
            if (this.Config.Profiles.AllProfiles.Count > 0)
            {
                string new_name = new List<string>(this.Config.Profiles.AllProfiles.Keys)[0];
                this.Config.Profiles.Current = this.Config.Profiles.AllProfiles[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.AllProfiles.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;

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

            this.Update(PreferencesUpdateStatus.ConfigSetRenamed);
            this.customer_number_regexentry.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 (Configurations.ProfilePreferences profile1 in this.Config.Profiles.AllProfiles.Values)
            {
                if (profile1.IgnoreMissingArchive == true)
                    continue;

                foreach (Configurations.ProfilePreferences profile2 in this.Config.Profiles.AllProfiles.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 (Configurations.ProfilePreferences profile3 in this.Config.Profiles.AllProfiles.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 OnShowIDifferenceLinkbuttonClicked(object sender, EventArgs e)
        {
            string title = Catalog.GetString("Description Show Differences of Back Projections");
            string message = Catalog.GetString
            (
                 "Select this option if you want to see the difference line between the following spectra:" +
                 "\n\t - the back projection of the acquired spectrum" +
                 "\n\t - the back projection of the substance reference spectrum" +
                 "\nPlease note that the difference line has an own scalling on the axis on the right side."
            );

            ExtToolTip.SetDialog(sender as Gtk.LinkButton,
                           Gtk.Stock.DialogInfo,
                           title,
                           message);
        }

        private void OnDeactivateMandatoryLinkbuttonClicked(object sender, EventArgs e)
        {
            string title = Catalog.GetString("Description Complementary Test as Mandatory");
            string message = Catalog.GetString
            (
                 "If you have chosen this option then you have to fill out the complementary tests " + 
                                        "/ identity tests for the measuring protocol."
            );

            ExtToolTip.SetDialog(sender as Gtk.LinkButton,
                           Gtk.Stock.DialogInfo,
                           title,
                           message);
        }

        private void OnPrintValidationLinkbuttonClicked(object sender, EventArgs e)
        {
            string title = Catalog.GetString("Description Print Validation within Protocol");
            string message = Catalog.GetString
            (
                 "If you have chosen this option then some parts of the validation document will be insert in " +
                 "the measuring protocol"
            );

            ExtToolTip.SetDialog(sender as Gtk.LinkButton,
                           Gtk.Stock.DialogInfo,
                           title,
                           message);
        }

        private void OnBAKLinkbuttonClicked(object sender, EventArgs e)
        {
            string title = Catalog.GetString("Description BAK Marking");
            string message = Catalog.GetString
            (
                 "If you have chosen this option then the BAK marking will be shown " +
                 "and appears on the measurment protocol and on the label print."               
            );

            ExtToolTip.SetDialog(sender as Gtk.LinkButton,
                           Gtk.Stock.DialogInfo,
                           title,
                           message);
        }

        #endregion
    }
}