// 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.ApoIdentCommon;
using Hiperscan.ApoIdentCore;
using Hiperscan.ApoIdentCore.Misc;
using Hiperscan.ApoIdentCommon.ApoConfig;
using Hiperscan.ApoIdentCommon.ApoConfig.Enums;

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.Control.ProfileManager.AllProfiles.ContainsKey(name) == true)
            {
                Plugin.host.ShowInfoMessage(this.preferences_dialog,
                                                Catalog.GetString("A configuration profile with name \"{0}\" already exists."),
                                                name);
                return;
            }

            Base64AddressDialog dialog = new Base64AddressDialog(this.preferences_dialog);

            GuiDesigner.SetSchema(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.Control.ProfileManager.CurrentProfile = new ProfileSettings();
            this.Control.ProfileManager.CurrentProfile.Name = name;

            this.Control.ProfileManager.CurrentProfile.CustomerNumber = entries[0];
            this.Control.ProfileManager.CurrentProfile.Company = entries[1];
            this.Control.ProfileManager.CurrentProfile.Street = entries[2];
            this.Control.ProfileManager.CurrentProfile.Town = entries[3];
            this.Control.ProfileManager.CurrentProfile.Archive = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
                                                                       ApoIdentInfo.NAME,
                                                                       Catalog.GetString("Archive"),
                                                                       FileIOHelper.ConvertToValidFilename(name));


            this.Control.ProfileManager.CurrentProfile.Base64ConversionCreator = entries[4];
            this.Control.ProfileManager.CurrentProfile.Base64ConversionTimestamp = DateTime.Parse(entries[5], System.Globalization.CultureInfo.InvariantCulture);

            this.Control.ProfileManager.CurrentProfile.FileNameStart = FilenameStartTypes.SubstanceName;

            if (this.Control.ProfileManager.IsDemoVersion == true)
            {
                this.Control.ProfileManager.IsDemoVersion = false;
                this.Control.ProfileManager.AllProfiles.Clear();
            }

            this.Control.ProfileManager.AllProfiles.Add(name, this.Control.ProfileManager.CurrentProfile);

            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 you want to delete the profile '{0}'?"),
                                                   this.Control.ProfileManager.CurrentProfile.Name);

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

            this.Control.ProfileManager.AllProfiles.Remove(this.Control.ProfileManager.CurrentProfile.Name);
            if (this.Control.ProfileManager.AllProfiles.Count > 0)
            {
                string new_name = new List<string>(this.Control.ProfileManager.AllProfiles.Keys)[0];
                this.Control.ProfileManager.CurrentProfile = this.Control.ProfileManager.AllProfiles[new_name];
            }
            else
            {
                this.Control.ProfileManager.CurrentProfile = null;
            }

            this.Update(PreferencesUpdateStatus.ConfigSetRemoved);
        }

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

            if (this.Control.ProfileManager.AllProfiles.ContainsKey(name) == true)
            {
                Plugin.host.ShowInfoMessage(this.preferences_dialog,
                    Catalog.GetString("A configuration profile with name \"{0}\" already exists."),
                    name);
                return;
            }

            string old_name = this.Control.ProfileManager.CurrentProfile.Name;

            ProfileSettings profile = this.Control.ProfileManager.CurrentProfile;
            this.Control.ProfileManager.AllProfiles.Remove(old_name);
            profile.Name = name;
            this.Control.ProfileManager.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 profile");
            if (new_config == false)
                title = Catalog.GetString("Rename profile");

            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 the name of the configuration profile:"));
            Entry entry = new Entry(Catalog.GetString("New profile"));
            if (new_config == false)
                entry.Text = this.Control.ProfileManager.CurrentProfile.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.IconList = ApoIdentStock.FinderIcons;

            GuiDesigner.SetSchema(dialog);
            dialog.ShowAll();
            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.Control.ProfileManager.CurrentProfile == null)
                return;

            Dictionary<string, List<string>> messages = new Dictionary<string, List<string>>();
            foreach (ProfileSettings profile1 in this.Control.ProfileManager.AllProfiles.Values)
            {
                if (profile1.IgnoreMissingArchive == true)
                    continue;

                foreach (ProfileSettings profile2 in this.Control.ProfileManager.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 (ProfileSettings profile3 in this.Control.ProfileManager.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 queries. 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, ProfileManager profile_manager)
        {
            if (profile_manager.IsDemoVersion == true)
            {
                MessageDialog dialog = new MessageDialog(parent, DialogFlags.Modal, MessageType.Warning, ButtonsType.Ok, true,
                                                         ProfileManager.DEMO_VERSION_NOTE);

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

                GuiDesigner.SetSchema(dialog);
                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:
	 - The back-projection of the acquired spectrum
	 - The back-projection of the substance reference spectrum
Please note the changed scaling for the displayed difference line."
            );

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

        private void OnDeactivateMandatoryLinkbuttonClicked(object sender, EventArgs e)
        {
            string title = Catalog.GetString("Description 'Additional Tests mandatory'");
            string message = Catalog.GetString
            (
"If you choose this option, then the complementary tests / identity tests will become mandatory for creating 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 for Print Validation in Protocol");
            string message = Catalog.GetString
            (
"If you choose this option, then parts of the validation document will be inserted into the measuring protocol."
            );

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

        private void CertificationControlClicked(object sender, EventArgs e)
        {
            string title = Catalog.GetString("Description Certification Control");
            string message = Catalog.GetString("If you choose this option, the certification control according to § 6 ApBetrO will be activated and output in the 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 Designation'");
            string message = Catalog.GetString
            (
"If you choose this option, then the BAK marking will be shown and appears on the measurement protocol and on the print label."
            );

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

        #endregion
    }
}
