// 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 Hiperscan.Common;
using Hiperscan.Common.I18n;
using Hiperscan.Unix;

namespace Hiperscan.Extensions.ApoIdent
{

    public partial class Preferences
    {
        public static Preferences Start(ApoIdentApplication apo_ident_app)
        {
            return new Preferences(apo_ident_app);
        }

        private Preferences(ApoIdentApplication apo_ident_app)
        {
            this.ApoIdentApp = apo_ident_app;

            lock (this.ApoIdentApp.Control.Transaction)
            {
                this.ApoIdentApp = apo_ident_app;
                this.Config = apo_ident_app.Config;
                this.Config.StashAll();

                WaitWindow wait_window = new WaitWindow(this.ApoIdentApp.MainWindow,
                                                Catalog.GetString("Loading settings. Please wait..."),
                                                 600);

                Glade.XML gui = new Glade.XML(null, "ApoIdent.Resources.Glade.FinderWindow.glade", "preferences_dialog", "Hiperscan");
                gui.Autoconnect(this);

                this.preferences_dialog.SetWmclass(Plugin.name.ToLower(),
                                                   Plugin.name.ToLower());

                this.preferences_dialog.TransientFor = this.ApoIdentApp.MainWindow;

                this.InitializeDialog();
                this.preferences_dialog.Shown += this.OnDialogShown;
                wait_window.Destroy();

                this.preferences_dialog.IconList = ApoIdentStock.FinderIcons;

                bool check = false;
                do
                {
                    this.preferences_dialog.Run();
                    check = this.Check();
                }
                while (check == false);

                this.Close();
            }
        }

        private void InitializeDialog()
        {
            this.preferences_dialog.Title = Plugin.name + " " + Catalog.GetString("Preferences");
            this.InitProtocolManagmentComboBox();
            this.InitializeRegexEntries();
            this.InitLabelPrinter();
            this.SetInitialScrolledWindow();
            this.device_expander.Expanded = false;
            this.identmodule_expander.Expanded = false;
            this.Update(PreferencesUpdateStatus.InitWindow);
        }

        private void ChangeScrolledBarStyle()
        {

        }

        private void InitProtocolManagmentComboBox()
        {
            ListStore store = new ListStore(typeof(string));
            CellRendererText text = new CellRendererText();

            this.report_management_combo.Clear();
            this.report_management_combo.PackStart(text, false);
            this.report_management_combo.SetAttributes(text, "text", 0);
            this.report_management_combo.Model = store;

            foreach (ProtocolType protocol_type in Enum.GetValues(typeof(ProtocolType)))
            {
                //Deactivate following two lines for activating rezepturdoku
                if (protocol_type == ProtocolType.RezepturDoku)
                    continue;

                this.report_management_combo.AppendText(StringEnum.GetStringValue(protocol_type));
            }
        }



        private void AddChangeEvents()
        {
            this.config_combo.Changed += this.OnConfigComboChanged;

            this.customer_number_regexentry.Entry.Changed += this.OnCustomerNumberEntryChanged;
            this.name_info_regexentry.Entry.Changed += this.OnCompanyEntryChanged;
            this.street_info_regexentry.Entry.Changed += this.OnStreetEntryChanged;
            this.town_info_regexentry.Entry.Changed += this.OnTownEntryChanged;
            this.archive_entry.Changed += this.OnArchiveEntryChanged;

            this.default_filename_start_combo.Changed += this.OnDefaultFileNameStartComboChanged;
            this.report_management_combo.Changed += this.OnReportManagementComboChanged;
            this.country_combobox.Changed += this.OnCountryComboBoxChanged;
            this.bak_checkbutton.Toggled += this.OnBAKCheckbittonToggled;
            this.show_difference_checkbutton.Toggled += this.OnShowDifferenceCheckbittonToggled;
            this.mandatory_checkbutton.Toggled += this.OnMandatoryCheckButtonToggled;
            this.print_validation_checkbutton.Toggled += this.OnPrintValidationCheckButtonToggled;

            this.AddDeviceEvents();
            this.AddIdentModuleEvents();
            this.AddSoftwareEvents();

            this.label_printer_combo.Changed += this.OnLabelPrinterComboChanged;
            this.page_size_combo.Changed += this.OnPageSizeComboChanged;

            this.label_orientation_combo.Changed += this.OnPrinterValueChanged;
            this.label_width_spin.Changed += this.OnPrinterValueChanged;
            this.label_height_spin.Changed += this.OnPrinterValueChanged;
            this.label_x_offset_spin.Changed += this.OnPrinterValueChanged;
            this.label_y_offset_spin.Changed += this.OnPrinterValueChanged;
            this.label_scale_factor_spin.Changed += this.OnPrinterValueChanged;
        }

        private void RemoveChangedEvents()
        {
            this.config_combo.Changed -= this.OnConfigComboChanged;

            this.customer_number_regexentry.Entry.Changed -= this.OnCustomerNumberEntryChanged;
            this.name_info_regexentry.Entry.Changed -= this.OnCompanyEntryChanged;
            this.street_info_regexentry.Entry.Changed -= this.OnStreetEntryChanged;
            this.town_info_regexentry.Entry.Changed -= this.OnTownEntryChanged;
            this.archive_entry.Changed -= this.OnArchiveEntryChanged;

            this.default_filename_start_combo.Changed -= this.OnDefaultFileNameStartComboChanged;
            this.report_management_combo.Changed -= this.OnReportManagementComboChanged;
            this.country_combobox.Changed -= this.OnCountryComboBoxChanged;
            this.bak_checkbutton.Toggled -= this.OnBAKCheckbittonToggled;
            this.show_difference_checkbutton.Toggled -= this.OnShowDifferenceCheckbittonToggled;
            this.mandatory_checkbutton.Toggled -= this.OnMandatoryCheckButtonToggled;
            this.print_validation_checkbutton.Toggled -= this.OnPrintValidationCheckButtonToggled;



            this.RemoveDeviceEvents();
            this.RemoveIdentModuleEvents();
            this.RemoveSoftwareEvents();

            this.label_printer_combo.Changed -= this.OnLabelPrinterComboChanged;
            this.page_size_combo.Changed -= this.OnPageSizeComboChanged;

            this.label_orientation_combo.Changed -= this.OnPrinterValueChanged;
            this.label_width_spin.Changed -= this.OnPrinterValueChanged;
            this.label_height_spin.Changed -= this.OnPrinterValueChanged;
            this.label_x_offset_spin.Changed -= this.OnPrinterValueChanged;
            this.label_y_offset_spin.Changed -= this.OnPrinterValueChanged;
            this.label_scale_factor_spin.Changed -= this.OnPrinterValueChanged;
        }


        #region config managment section

        private void FillConfigCombo()
        {
            ListStore store = new ListStore(typeof(string));
            CellRendererText text = new CellRendererText();

            this.config_combo.Clear();
            this.config_combo.PackStart(text, false);
            this.config_combo.SetAttributes(text, "text", 0);
            this.config_combo.Model = store;
            foreach (string profile_name in this.Config.Profiles.AllProfiles.Keys)
                this.config_combo.AppendText(profile_name);
        }


        private void OnConfigComboChanged(object o, EventArgs e)
        {
            this.Config.Profiles.Current = this.Config.Profiles.AllProfiles[this.config_combo.ActiveText];
            this.Update(PreferencesUpdateStatus.UserConfigComboChanged);
        }

        private void UpdateConfigComboSection()
        {
            if (this.Config.Profiles.Current == null)
            {
                this.config_combo.Sensitive = false;
                this.add_config_button.Sensitive = true;
                this.remove_config_button.Sensitive = false;
                this.rename_config_button.Sensitive = false;
            }
            else
            {
                this.config_combo.Sensitive = true;
                this.add_config_button.Sensitive = true;
                this.remove_config_button.Sensitive = this.Config.Profiles.AllProfiles.Count > 1;
                this.rename_config_button.Sensitive = this.Config.Profiles.IsDemoVersion == false;

                this.config_combo.Active = this.Config.Profiles.CurrentIndex(this.Config.Profiles.Current);
            }
        }

        #endregion config managment section


        #region profile settings

        private void OnCustomerNumberEntryChanged(object sender, EventArgs e)
        {
            this.Config.Profiles.Current.CustomerNumber = StringHelper.CleanUserInputString(this.customer_number_regexentry.Entry.Text);
        }

        private void OnCompanyEntryChanged(object sender, EventArgs e)
        {
            this.Config.Profiles.Current.Company = StringHelper.CleanUserInputString(this.name_info_regexentry.Entry.Text);
        }

        private void OnStreetEntryChanged(object sender, EventArgs e)
        {
            this.Config.Profiles.Current.Street = StringHelper.CleanUserInputString(this.street_info_regexentry.Entry.Text);
        }

        private void OnTownEntryChanged(object sender, EventArgs e)
        {
            this.Config.Profiles.Current.Town = StringHelper.CleanUserInputString(this.town_info_regexentry.Entry.Text);
        }

        private void OnDefaultFileNameStartComboChanged(object sender, EventArgs e)
        {
            this.Config.Profiles.Current.FileNameStart = (Configurations.FilenameStartTypes)this.default_filename_start_combo.Active;
        }

        private void OnArchiveEntryChanged(object sender, EventArgs e)
        {
            this.Config.Profiles.Current.Archive = this.archive_entry.Text;
        }

        private void OnArchiveEntryMouseOver(object sender, EnterNotifyEventArgs e)
        {
            this.archive_entry.TooltipText = this.archive_entry.Text;
        }

        private void OnArchiveButtonClicked(object sender, EventArgs e)
        {
            using (Gtk.FileChooserDialog chooser = new Gtk.FileChooserDialog(
                Catalog.GetString("Select Archive Directory"),
                this.preferences_dialog,
                FileChooserAction.SelectFolder))
            {
                chooser.AddButton(Gtk.Stock.Apply, Gtk.ResponseType.Ok);
                chooser.AddButton(Gtk.Stock.Cancel, Gtk.ResponseType.Cancel);
                chooser.DoOverwriteConfirmation = true;
                chooser.SetCurrentFolder(this.archive_entry.Text);

                chooser.Modal = true;
                chooser.IconList = ApoIdentStock.FinderIcons;

                if ((ResponseType)chooser.Run() == ResponseType.Ok)
                    this.archive_entry.Text = chooser.Filename;

                chooser.Destroy();
            }
        }


        private void OnReportManagementComboChanged(object sender, EventArgs e)
        {
            this.Config.Profiles.Current.ExchangeData = DataExchange.Create((ProtocolType)this.report_management_combo.Active);
            this.Update(PreferencesUpdateStatus.ReportMangementChanged);
        }

        private void OnCountryComboBoxChanged(object sender, EventArgs e)
        {
            this.Config.Profiles.Current.ReportCountry = (Configurations.ReportCountryType)this.country_combobox.Active;
            this.Update(PreferencesUpdateStatus.ReportCountryChanged);
        }

        private void OnBAKCheckbittonToggled(object sender, EventArgs e)
        {
            this.Config.Profiles.Current.BAKMarkingActivated = this.bak_checkbutton.Active;
        }

        private void OnShowDifferenceCheckbittonToggled(object sender, EventArgs e)
        {
            this.Config.Profiles.Current.ShowDifference = this.show_difference_checkbutton.Active;
        }

        private void OnMandatoryCheckButtonToggled(object sender, EventArgs e)
        {
            this.Config.Profiles.Current.MandatoryForComplementaryTest = this.mandatory_checkbutton.Active;
        }

        private void OnPrintValidationCheckButtonToggled(object sender, EventArgs e)
        {
            this.Config.Profiles.Current.PrintValidationWhitinProtocol = this.print_validation_checkbutton.Active;
        }

        private void OnReportManagementButtonClicked(object sender, EventArgs e)
        {
            try
            {
                new DataExchangeSettingsDialog(this.Config.Profiles.Current.ExchangeData, this.preferences_dialog);
            }
            catch (Exception ex)
            {
                string message = String.Format(Catalog.GetString("Cannot open directory exchange settings dialog: {0}"), ex.Message);
                Plugin.host.ShowInfoMessage(this.preferences_dialog, message);
            }
        }

        private void UpdateProfileSection()
        {
            this.customer_number_regexentry.Entry.Text = String.Empty;
            this.name_info_regexentry.Entry.Text = String.Empty;
            this.street_info_regexentry.Entry.Text = String.Empty;
            this.town_info_regexentry.Entry.Text = String.Empty;
            this.default_filename_start_combo.Active = (int)Configurations.FilenameStartTypes.SubstanceName;
            this.archive_entry.Text = String.Empty;
            this.report_management_combo.Active = (int)ProtocolType.ApoIdent;
            this.show_difference_checkbutton.Active = false;
            this.mandatory_checkbutton.Active = false;
            this.archive_entry.Text = String.Empty;
            this.bak_checkbutton.Active = false;

            switch (Locale.Language)
            {

                case "de":
                    switch (Locale.Country)
                    {

                        case "at":
                            this.country_combobox.Active = (int)Configurations.ReportCountryType.Austria;
                            break;

                        case "ch":
                            this.country_combobox.Active = (int)Configurations.ReportCountryType.Switzerland;
                            break;

                        case "en":
                            this.country_combobox.Active = (int)Configurations.ReportCountryType.GreatBritain;
                            break;

                        default:
                            break;

                    }
                    break;

                default:
                    this.country_combobox.Active = (int)Configurations.ReportCountryType.GreatBritain;
                    break;

            }

            if (this.Config.Profiles.Current != null)
            {
                this.customer_number_regexentry.Entry.Text = this.Config.Profiles.Current.CustomerNumber;
                this.name_info_regexentry.Entry.Text = this.Config.Profiles.Current.Company;
                this.street_info_regexentry.Entry.Text = this.Config.Profiles.Current.Street;
                this.town_info_regexentry.Entry.Text = this.Config.Profiles.Current.Town;

                this.default_filename_start_combo.Active = (int)this.Config.Profiles.Current.FileNameStart;
                this.archive_entry.Text = this.Config.Profiles.Current.Archive;
                this.report_management_combo.Active = (int)this.Config.Profiles.Current.ExchangeData.ProtocolType;
                this.country_combobox.Active = (int)this.Config.Profiles.Current.ReportCountry;
                this.bak_checkbutton.Active = this.Config.Profiles.Current.BAKMarkingActivated;
                this.show_difference_checkbutton.Active = this.Config.Profiles.Current.ShowDifference;
                this.mandatory_checkbutton.Active = this.Config.Profiles.Current.MandatoryForComplementaryTest;
                this.print_validation_checkbutton.Active = this.Config.Profiles.Current.PrintValidationWhitinProtocol;
                this.archive_entry.Text = this.Config.Profiles.Current.Archive;

                if (this.Config.Profiles.Current.ReportCountry == Configurations.ReportCountryType.Germany &&
                    this.Config.Profiles.Current.ExchangeData.ProtocolType == ProtocolType.ApoIdent)
                {
                    this.bak_label.Sensitive = true;
                    this.bak_checkbutton.Sensitive = true;
                    this.show_bak_linkbutton.Sensitive = true;
                }
                else
                {
                    this.bak_label.Sensitive = false;
                    this.bak_checkbutton.Sensitive = false;
                    this.show_bak_linkbutton.Sensitive = false;
                }

                 
                if (this.Config.Profiles.Current.ExchangeData.ProtocolType == ProtocolType.ApoIdent)
                {
                    this.mandary_label.Sensitive = true;
                    this.mandatory_checkbutton.Sensitive = true;
                    this.show_deactive_mandatory_linkbutton.Sensitive = true;
                }
                else
                {
                    this.mandary_label.Sensitive = false;
                    this.mandatory_checkbutton.Sensitive = false;
                    this.show_deactive_mandatory_linkbutton.Sensitive = false;
                }

                if (this.Config.Profiles.Current.ReportCountry != Configurations.ReportCountryType.GreatBritain)
                {
                    this.print_validation_label.Sensitive = true;
                    this.print_validation_checkbutton.Sensitive = true;
                    this.show_print_validation_linkbutton.Sensitive = true;
                }
                else
                {
                    this.print_validation_label.Sensitive = false;
                    this.print_validation_checkbutton.Sensitive = false;
                    this.show_print_validation_linkbutton.Sensitive = false;
                }

                this.profile_table.Sensitive = true;
            }
            else
            {
                this.profile_table.Sensitive = false;
            }

            if (Locale.Language == "de")
            {
                this.report_management_combo.Visible = true;
                this.report_management_label.Visible = true;
            }
            else
            {
                this.report_management_combo.Visible = false;
                this.report_management_label.Visible = false;
            }
        }

        private void UpdateReportManagementSettingsButton()
        {
            if (this.Config.Profiles.Current == null ||
                this.Config.Profiles.Current.ExchangeData.ProtocolType == ProtocolType.ApoIdent ||
                Locale.Language != "de")
            {
                this.report_management_button.Visible = false;
            }
            else
            {
                this.report_management_button.Visible = true;
            }
        }

        #endregion profile settings

        private bool Check()
        {
            if (this.Config.IdentModuleSettings.IdentificationMode == Configurations.IdentificationMode.Custom &&
                String.IsNullOrEmpty(this.Config.IdentModuleSettings.Url) == true)
            {
                Plugin.host.ShowInfoMessage(this.preferences_dialog,
                    Catalog.GetString("Please enter an url in the field 'IP Address' in IdentModule settings."));
                this.close_button.Sensitive = true;
                return false;
            }

            if (this.Config.IdentModuleSettings.IdentificationMode == Configurations.IdentificationMode.Custom &&
                this.Config.IdentModuleSettings.TcpPort < 0)
            {
                Plugin.host.ShowInfoMessage(this.preferences_dialog,
                    Catalog.GetString("Please enter a valid port number in the field 'Tcp port' in IdentModule settings."));
                this.close_button.Sensitive = true;
                return false;
            }

            if (this.Config.DeviceSettings.DeviceSearchMode == Configurations.DeviceSearchMode.Custom &&
                String.IsNullOrEmpty(this.Config.DeviceSettings.Url) == true)
            {
                Plugin.host.ShowInfoMessage(this.preferences_dialog,
                    Catalog.GetString("Please enter an url in the field 'IP Address'in device settings."));
                this.close_button.Sensitive = true;
                return false;
            }

            if (this.Config.DeviceSettings.DeviceSearchMode == Configurations.DeviceSearchMode.Custom &&
                this.Config.DeviceSettings.TcpPort < 0)
            {
                Plugin.host.ShowInfoMessage(this.preferences_dialog,
                    Catalog.GetString("Please enter a valid port number in the field 'Tcp port' in device settings."));
                this.close_button.Sensitive = true;
                return false;
            }

            if (this.Config.Profiles.NeedCheck == true)
                return false;

                return true;
        }

        private void Close()
        {
            this.close_button.Sensitive = false;

            System.Threading.Tasks.Task.Run(() =>
            {
                Application.Invoke((sender, e2) =>
                {
                    Preferences.CheckForDemoVersion(this.preferences_dialog, this.Config);
                    this.CheckDirectoryEntriesForDoubleEntries();

                    this.preferences_dialog.Destroy();
                    this.Config.UnstashAll();
                    this.ApoIdentApp.Finder?.UpdateReferencingDir(this.Config.Profiles.Current.ArchiveMissing);
                    try
                    {
                        this.Config.WriteToXmlFile();
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Error while saving apo-ident configuration file: {0}", ex);
                    }
                });
            });
        }

        private ApoIdentApplication ApoIdentApp { get; set; }
        private Configurations Config { get; set; }
        private int MainThread { get; set; } = System.Threading.Thread.CurrentThread.ManagedThreadId;
    }
}