// Created with MonoDevelop
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2022 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.Threading.Tasks;
using Glade;
using Gtk;
using Hiperscan.ApoIdentCore.GuiControl;
using Hiperscan.Extensions.ApoIdent.Widgets;
using Hiperscan.ApoIdentCommon.ApoConfig.Enums;
using Hiperscan.ApoIdentCommon.ApoConfig.Internationalization;
using Hiperscan.GtkExtensions;
using Hiperscan.GuiExtensions;
using Hiperscan.Unix;

namespace Hiperscan.Extensions.ApoIdent
{
#pragma warning disable CS0618 // Typ oder Element ist veraltet

    public partial class ApoIdentApplication
    {
        [Widget] Gtk.Window main_window = null;


        [Widget] Gtk.Alignment main_alignment = null;
        [Widget] Gtk.EventBox menu_eventbox = null;
        [Widget] Gtk.EventBox form_eventbox = null;
        [Widget] Gtk.Table form_table = null;


        [Widget] Gtk.EventBox line1_eventbox = null;
        [Widget] Gtk.EventBox line2_eventbox = null;
        [Widget] Gtk.EventBox line3_eventbox = null;
        [Widget] Gtk.EventBox line4_eventbox = null;
        [Widget] Gtk.EventBox line5_eventbox = null;
        [Widget] Gtk.EventBox line6_eventbox = null;

        [Widget] Gtk.Label adjust_label = null;

        [Widget] Gtk.Image animation_state_image = null;
        [Widget] Gtk.Image animation_info_image = null;
        [Widget] Gtk.Label animation_state_label = null;
        [Widget] Gtk.Alignment animation_menuline_alignment = null;
        [Widget] Gtk.EventBox animation_frame_eventbox = null;


        private void DrawGui()
        {

            Glade.XML gui = new Glade.XML(null, "Hiperscan.Extensions.ApoIdent.ApoIdentApplication.GuiInit.apo_ident_window.glade", "main_window", "Hiperscan");
            gui.Autoconnect(this);

            this.InitGuiSyncControl(this.main_window, this.Control.GuiSyncControl);

            this.SyncControl.EnterInitGUI();

            CellRendererInfo.Init();
            this.GuiDesigner.InitComboBoxes(this.MainWindow);
            this.InitMainWindow();

            this.InitMenuSection();
            this.InitPharmacySection();
            this.InitSubstanceSection();
            this.InitSpecimenSection();
            this.InitMeasuringSection();
            this.InitResultSection();
            this.InitProtocolSection();
            this.InitStatusSection();

            this.InitAnimation();
            this.InitColorSchema();

            this.MainWindow.Opacity = 0;
            GuiDesigner.SetSchema(this.MainWindow, true);

            this.SetPriceLabelSize();
            this.InitAdjustmentFormTable();
            this.InitBakMarking();
            this.InitFineAdjustment();

            this.MainWindow.Visible = false;
            this.SyncControl.LeaveInitGUI();

            Task.Run(() => this.ShowFinalResult());
        }

        private void ShowFinalResult()
        {
            System.Threading.Thread.Sleep(100);

            Application.Invoke((sender, e) =>
            {
                this.Control.GlobalStates.Busy = true;
                UpdateArgs arg = UpdateArgs.GetReloadAllArg();
                arg.CursorState = CursorState.Busy;
                this.Update(arg);

                this.main_window.Visible = true;
                this.MainWindow.Opacity = 1;
                this.SetInitialFocus();
                this.InitScrolledWindow();


                this.MainWindow.SetPosition(WindowPosition.Center);;

                this.InitSplashscreen();
                this.Control.RunFirstConnection();
            });
        }

        private void InitMenuSection()
        {
            this.MenuQuickStepToolButton = this.GuiDesigner.CreateApoIdentToolButtonButton(ref this.menu_quickstep_toolbutton, ApoIdentIcon.QuickStep);
            this.MenuExitToolButton = this.GuiDesigner.CreateApoIdentToolButtonButton(ref this.menu_exit_toolbutton, ApoIdentIcon.Exit);
            this.MenuArchiveToolButton = this.GuiDesigner.CreateApoIdentToolButtonButton(ref this.menu_archive_toolbutton, ApoIdentIcon.Archive);
            this.MenuQueryToolButton = this.GuiDesigner.CreateApoIdentToolButtonButton(ref this.menu_query_toolbutton, ApoIdentIcon.Query);
            this.MenuResetToolButton = this.GuiDesigner.CreateApoIdentToolButtonButton(ref this.menu_reset_toolbutton, ApoIdentIcon.Referencing);
            this.MenuConnectToolButton = this.GuiDesigner.CreateApoIdentToolButtonButton(ref this.menu_connect_toolbutton, ApoIdentIcon.Connect);
            this.MenuSettingsToolButton = this.GuiDesigner.CreateApoIdentToolButtonButton(ref this.menu_settings_toolbutton, ApoIdentIcon.Settings);
            this.MenuSubstanceToolButton = this.GuiDesigner.CreateApoIdentToolButtonButton(ref this.menu_substance_toolbutton, ApoIdentIcon.Substance);
            this.MenuHelpTolButton = this.GuiDesigner.CreateApoIdentToolButtonButton(ref this.menu_help_toolbutton, ApoIdentIcon.Help);
            this.MenuCannabisTolButton = this.GuiDesigner.CreateApoIdentToolButtonButton(ref this.menu_cannabis_toolbutton, ApoIdentIcon.Cannabis);
            this.MenuInfoToolButton = this.GuiDesigner.CreateApoIdentToolButtonButton(ref this.menu_info_toolbutton, ApoIdentIcon.Info);
            this.MenuValidationToolButton = this.GuiDesigner.CreateApoIdentToolButtonButton(ref this.menu_validation_toolbutton, ApoIdentIcon.Validation);
        }

        private void InitPharmacySection()
        {
            this.GuiDesigner.ModifySectionMainLabel(this.pharmacy_section_label);

            this.PharmacyOperatorEntry = this.GuiDesigner.CreateOutLinedEntry(ref this.pharmacy_operator_entry);
            this.PharmacyOperatorEntry.GtkEntry.MaxLength = this.Control.PharmacyManager.Operator.FieldLength;
            this.PharmacyOperatorEntry.ErrorMessage = this.Control.PharmacyManager.Operator.ErrorMessage;
            this.PharmacyOperatorEntry.ValueChanged += this.OnPharmacyOperatorEntryChanged;

            this.InitPharmacyOperatorCompletion();
        }

        private void InitSubstanceSection()
        {
            this.GuiDesigner.ModifySectionMainLabel(this.substance_section_label);

            this.SubstanceClassifierExchangeButton = this.GuiDesigner.CreateApoIdentButton(ref this.substance_classifier_button, ApoIdentIcon.ClassifierChange);
            this.SubstanceInfoButton = this.GuiDesigner.CreateApoIdentButton(ref this.substance_info_button, ApoIdentIcon.SubstanceWarning);
            this.SubstanceDataExchangeButton = this.GuiDesigner.CreateApoIdentButton(ref this.substance_data_exchange_button, ApoIdentIcon.DataExchangeLennartz);
            this.SubstanceClearButton = this.GuiDesigner.CreateApoIdentButton(ref this.substance_clear_button, ApoIdentIcon.Clear);

            this.SubstanceSearchEntry = this.GuiDesigner.CreateOutLinedEntry(ref this.substance_search_entry);
            this.InitSubstanceSearchEntry();
            this.SubstanceSearchEntry.GtkEntry.FocusOutEvent += this.OnSubstanceSearchEntryFocusOut;
            this.SubstanceSearchEntry.GtkEntry.Activated += this.OnSubstanceSearchEntryActivated;

            this.SubstanceValidationLinklabel = this.GuiDesigner.CreateLinkLabel(ref this.substance_validation_label);
            this.SubstanceValidationLinklabel.Clicked += this.OnValidationReportButtonClicked;

            this.SubstanceSynonymsOutputLabel = this.GuiDesigner.CreateFlexLabel(this.substance_synonyms_output_eventbox);
            this.SubstanceSynonymsOutputLabel.Text = "Mal sehen,wie das aussieht";
            this.SubstanceSynonymsOutputLabel.Sensitive = false;

            this.SubstanceTestForOutputLabel = this.GuiDesigner.CreateFlexEllipsizeLabel(ref this.substance_test_for_output_label);
        }

        private void InitSpecimenSection()
        {
            this.GuiDesigner.ModifySectionMainLabel(this.specimen_section_label);

            this.SpecimenPpnEntry = this.GuiDesigner.CreateOutLinedEntry(ref this.specimen_ppn_entry);
            this.SpecimenPpnEntry.GtkEntry.MaxLength = this.Control.SpecimenManager.PPN.FieldLength;
            this.SpecimenPpnEntry.ErrorMessage = this.Control.SpecimenManager.PPN.ErrorMessage;
            this.SpecimenPpnEntry.ValueChanged += this.OnPpnEntryChanged;

            this.SpecimenProducerEnntry = this.GuiDesigner.CreateOutLinedEntry(ref this.specimen_producer_entry);
            this.SpecimenProducerEnntry.GtkEntry.MaxLength = this.Control.SpecimenManager.Producer.FieldLength;
            this.SpecimenProducerEnntry.ErrorMessage = this.Control.SpecimenManager.Producer.ErrorMessage;
            this.SpecimenProducerEnntry.ValueChanged += this.OnProducerEntryChanged;

            this.SpecimenBatchEntry = this.GuiDesigner.CreateOutLinedEntry(ref this.specimen_batch_entry);
            this.SpecimenBatchEntry.GtkEntry.MaxLength = this.Control.SpecimenManager.Batch.FieldLength;
            this.SpecimenBatchEntry.ErrorMessage = this.Control.SpecimenManager.Batch.ErrorMessage;
            this.SpecimenBatchEntry.ValueChanged += this.OnBatchEntryChanged;

            this.SpecimenQuantityEntry = this.GuiDesigner.CreateOutLinedEntry(ref this.specimen_quantity_entry);
            this.SpecimenQuantityEntry.GtkEntry.MaxLength = this.Control.SpecimenManager.ReferenceQuantity.FieldLength;
            this.SpecimenQuantityEntry.ErrorMessage = this.Control.SpecimenManager.ReferenceQuantity.ErrorMessage;
            this.SpecimenQuantityEntry.ValueChanged += this.OnReferenceQuantityValueChanged;

            this.SpecimenQuantityComboBox = this.GuiDesigner.CreateOutLinedQuantityComboBox(ref this.specimen_quantity_combobox);
            this.SpecimenQuantityComboBox.ErrorMessage = this.Control.SpecimenManager.ReferenceQuantity.ErrorMessage;
            this.SpecimenQuantityComboBox.ValueChanged += this.OnReferenceQuantityUnitChanged;

            this.SpecimenDistributorEntry = this.GuiDesigner.CreateOutLinedEntry(ref this.specimen_distributor_entry);
            this.SpecimenDistributorEntry.GtkEntry.MaxLength = this.Control.SpecimenManager.Distributor.FieldLength;
            this.SpecimenDistributorEntry.ErrorMessage = this.Control.SpecimenManager.Distributor.ErrorMessage;
            this.SpecimenDistributorEntry.ValueChanged += this.OnDistributorEntryChanged;

            this.SpecimenPriceEntry = this.GuiDesigner.CreateOutLinedEntry(ref this.specimen_price_entry);
            this.SpecimenPriceEntry.GtkEntry.MaxLength = this.Control.SpecimenManager.Price.FieldLength;
            this.SpecimenPriceEntry.ErrorMessage = this.Control.SpecimenManager.Price.ErrorMessage;
            this.SpecimenPriceEntry.ValueChanged += this.OnPriceEntryChanged;

            this.SpecimenExpiryDateEntry = this.GuiDesigner.CreateOutLineCalenderEntry(ref this.specimen_expiry_date_entry);
            this.SpecimenExpiryDateEntry.GtkEntry.MaxLength = this.Control.SpecimenManager.ExpiryDate.FieldLength;
            this.SpecimenExpiryDateEntry.ErrorMessage = this.Control.SpecimenManager.ExpiryDate.ErrorMessage;
            this.SpecimenExpiryDateEntry.ExactDateTimeFormat = this.Control.SpecimenManager.ExpiryDate.ParseDateFormat;
            this.SpecimenExpiryDateEntry.ValueChanged += this.OnExpiryDateChanged;

            this.SpecimenGracePeriodEntry = this.GuiDesigner.CreateOutLinedEntry(ref this.specimen_grace_entry);
            this.SpecimenGracePeriodEntry.GtkEntry.MaxLength = this.Control.SpecimenManager.GracePeriod.FieldLength;
            this.SpecimenGracePeriodEntry.ErrorMessage = this.Control.SpecimenManager.GracePeriod.ErrorMessage;
            this.SpecimenGracePeriodEntry.ValueChanged += this.OnGracePeriodValueChanged;

            this.SpecimenGracePeriodComboBox = this.GuiDesigner.CreateOutLinedGraceComboBox(ref this.specimen_grace_combobox);
            this.SpecimenGracePeriodComboBox.ErrorMessage = this.Control.SpecimenManager.GracePeriod.ErrorMessage;
            this.SpecimenGracePeriodComboBox.ValueChanged += this.OnGracePeriodUnitChanged;
            this.SpecimenGracePeriodComboBox.EnumComboBox.IsPlural = true;

            this.SpecimenWeighingCorrEntry = this.GuiDesigner.CreateOutLinedEntry(ref this.specimen_weighing_corr_entry);
            this.SpecimenWeighingCorrEntry.GtkEntry.MaxLength = this.Control.SpecimenManager.CorrectionFactor.FieldLength;
            this.SpecimenWeighingCorrEntry.ErrorMessage = this.Control.SpecimenManager.CorrectionFactor.ErrorMessage;
            this.SpecimenWeighingCorrEntry.ValueChanged += this.OnCorrectionFactorEntryChanged;

            this.SpecimenTHCEntry = this.GuiDesigner.CreateOutLinedEntry(ref this.specimen_thc_entry);
            this.SpecimenTHCEntry.GtkEntry.MaxLength = this.Control.SpecimenManager.THC.FieldLength;
            this.SpecimenTHCEntry.ErrorMessage = this.Control.SpecimenManager.THC.ErrorMessage;
            this.SpecimenTHCEntry.ValueChanged += this.OnTHCEntryChanged;

            this.SpecimenCBDEntry = this.GuiDesigner.CreateOutLinedEntry(ref this.specimen_cbd_entry);
            this.SpecimenCBDEntry.GtkEntry.MaxLength = this.Control.SpecimenManager.CBD.FieldLength;
            this.SpecimenCBDEntry.ErrorMessage = this.Control.SpecimenManager.CBD.ErrorMessage;
            this.SpecimenCBDEntry.ValueChanged += this.OnCBDEntryChanged;

            this.SpecimenVarietyEntry = this.GuiDesigner.CreateOutLinedEntry(ref this.specimen_variety_entry);
            this.SpecimenVarietyEntry.GtkEntry.MaxLength = this.Control.SpecimenManager.Variety.FieldLength;
            this.SpecimenVarietyEntry.ErrorMessage = this.Control.SpecimenManager.Variety.ErrorMessage;
            this.SpecimenVarietyEntry.ValueChanged += this.OnVarietyEntryChanged;

            this.SpecimenDeliveryDateEntry = this.GuiDesigner.CreateOutLineCalenderEntry(ref this.specimen_delivery_date_entry);
            this.SpecimenDeliveryDateEntry.GtkEntry.MaxLength = this.Control.SpecimenManager.DeliveryDate.FieldLength;
            this.SpecimenDeliveryDateEntry.ErrorMessage = this.Control.SpecimenManager.DeliveryDate.ErrorMessage;
            this.SpecimenDeliveryDateEntry.ExactDateTimeFormat = this.Control.SpecimenManager.DeliveryDate.ParseDateFormat;
            this.SpecimenDeliveryDateEntry.ValueChanged += this.OnDeliveryDateChanged;

            this.InitSpecimenProducerCompletion();
        }

        private void InitMeasuringSection()
        {
            this.GuiDesigner.ModifySectionMainLabel(this.measuring_section_label);

            this.GuiDesigner.SetMeasuringAdviceColor(this.measuring_advice_label);


            this.MeasuringStartButton = new MeasuringButton(this.measuring_start_button,
                                                       this.measuring_abort_button,
                                                       this.measuring_advice_label);

   
            this.GuiDesigner.SetMeasruringTimerLabelFontSize(measuring_time_label);
            this.GuiDesigner.SetMeasruringTimerLabelFontSize(measuring_time_output_label);
        }

        private void InitResultSection()
        {
            this.GuiDesigner.ModifySectionMainLabel(this.result_section_label);

            this.ResultNirLinklabel = this.GuiDesigner.CreateLinkLabel(ref this.result_nir_label);
            this.ResultNirLinklabel.Clicked += this.OnResultNirButtonClicked;

            this.ResultRatingLinklabel = this.GuiDesigner.CreateLinkLabel(ref this.result_rating_label);
            this.ResultRatingLinklabel.Clicked += this.OnResultRatingButtonClicked;

            this.ResultAdditionTestLinklabel = this.GuiDesigner.CreateLinkLabel(ref this.result_additional_test_label);
            this.ResultAdditionTestLinklabel.Clicked += this.OnResultAdditionalTestsClicked;

            this.ResultSuggestionLinklabel = this.GuiDesigner.CreateLinkLabel(ref this.result_suggestion_label);
            this.ResultSuggestionLinklabel.Clicked += this.OnResultSuggestionButtonClicked;


            this.ResultCommentEntry = this.GuiDesigner.CreateOutLinedEntry(ref this.result_comment_entry);
            this.ResultCommentEntry.GtkEntry.MaxLength = this.Control.ResultManager.Comment.FieldLength;
            this.ResultCommentEntry.IsValid = true;
            this.ResultCommentEntry.ValueChanged += this.OnResultCommentEntryChanged;

            this.ResultClassificationOutputLabel = this.GuiDesigner.CreateOutLinedLabel(ref this.result_classification_output_label);
            this.ResultClassificationOutputLabel.UseMarkup = true;
            this.ResultClassificationOutputLabel.IsValid = true;
            this.GuiDesigner.SetClassificationLabelFontSize(this.ResultClassificationOutputLabel);

            this.ResultAdditionlTestOutputLabel = this.GuiDesigner.CreateOutLinedLabel(ref this.result_additional_test_output_label);
            this.ResultAdditionlTestOutputLabel.PlaceHolderText = Catalog.GetString("(empty)");
            this.ResultAdditionlTestOutputLabel.Text = String.Empty;

            this.result_fail_image.Pixbuf = this.GuiDesigner.ResultFailPicture;
            this.result_ok_image.Pixbuf = this.GuiDesigner.ResultOkPicture;
        }

        private void InitProtocolSection()
        {
            this.GuiDesigner.ModifySectionMainLabel(this.protocol_section_label);

            this.ProtocolSaveToolButton = this.GuiDesigner.CreateApoIdentToolButtonButton(ref this.protocol_save_toolbutton, ApoIdentIcon.Save);
            this.ProtocolPdfToolButton = this.GuiDesigner.CreateApoIdentToolButtonButton(ref this.protocol_pdf_toolbutton, ApoIdentIcon.Pdf);
            this.ProtocolPrintToolButton = this.GuiDesigner.CreateApoIdentToolButtonButton(ref this.protocol_print_toolbutton, ApoIdentIcon.Print);
            this.ProtocolLabelPrintToolButton = this.GuiDesigner.CreateApoIdentToolButtonButton(ref this.protocol_label_print_toolbutton, ApoIdentIcon.LabelPrint);
        }

        private void InitStatusSection()
        {
            this.GuiDesigner.SetStatusLabelFontSize(this.state_device_label);
            this.GuiDesigner.SetStatusLabelFontSize(this.state_devicetype_label);
        }

        private void InitAnimation()
        {
            this.Animation = new Animation(this.animation_state_image,
                                             this.animation_state_label,
                                             this.animation_info_image,
                                             this.animation_frame_eventbox,
                                             this.animation_menuline_alignment,
                                             this.GuiDesigner.Logo,
                                           this.Control.FileSystem.OpenPdf);
        }

        private void InitColorSchema()
        {
            this.GuiDesigner.SetTimerLabelColor(this.measuring_time_label);
            this.GuiDesigner.SetTimerLabelColor(this.measuring_time_output_label);

            this.GuiDesigner.SetFormLineColor(this.line1_eventbox);
            this.GuiDesigner.SetFormLineColor(this.line2_eventbox);
            this.GuiDesigner.SetFormLineColor(this.line3_eventbox);
            this.GuiDesigner.SetFormLineColor(this.line4_eventbox);
            this.GuiDesigner.SetFormLineColor(this.line5_eventbox);
            this.GuiDesigner.SetFormLineColor(this.line6_eventbox);

            this.GuiDesigner.SetFormBackGround(this.form_eventbox);
            this.GuiDesigner.SetFormBackGround(this.protocol_toolbar);
            this.GuiDesigner.SetFormBackGround(this.state_eventbox);
            this.GuiDesigner.SetFormBackGround(this.menu_eventbox);
            this.GuiDesigner.SetFormBackGround(this.menu_toolbar);
        }

        private void InitAdjustmentFormTable()
        {
            this.GuiDesigner.FormatTable(this.form_table);
        }

        private void InitBakMarking()
        {
            this.SubstanceBAKMarkingWidget = this.GuiDesigner.CreateBakMarking(this.substance_bak_marking_table);
            this.SubstanceBAKMarkingWidget.ValueChanged += this.OnBakMarkingChanged;
        }

        private void InitFineAdjustment()
        {
            this.ResultAdditionlTestOutputLabel.Height = this.ResultCommentEntry.GtkEntry.Allocation.Height;

            int width = (this.SubstanceClearButton.GtkButton.Allocation.Width + (int)GuiDesigner.LAST_COLUMN_SPACING) * 2;
            if (this.SubstanceValidationLinklabel.Width > width)
                width = this.SubstanceValidationLinklabel.Width;
            if (this.ResultSuggestionLinklabel.Width > width)
                width = this.ResultSuggestionLinklabel.Width;
            this.adjust_label.WidthRequest = width;

            int height = this.SubstanceClearButton.GtkButton.Allocation.Height;
            if (height > this.substance_test_for_label.Allocation.Height)
                this.substance_test_for_label.HeightRequest = height;
            if (height > this.substance_classifier_label.Allocation.Height)
                this.substance_classifier_label.HeightRequest = height;
        }

        private void InitScrolledWindow()
        {
            this.ScrolledWindow = new ScrolledWindowSetter(this.form_eventbox, this.main_alignment);
            this.ScrolledWindow.MaximizeBySettingScrolledWindow = true;
            this.ScrolledWindow.SetScrollBars();
        }

        private void SetInitialFocus()
        {
            this.PharmacyOperatorEntry.GtkEntry.HasFocus = true;
        }

        private void WriteInitialSizes()
        {
            Console.WriteLine("MainWindow Size: {0} x {1}",
                              this.MainWindow.Allocation.Width,
                              this.MainWindow.Allocation.Height);
        }

        private void SetPriceLabelSize()
        {
            int width = 0;
            foreach (string currency in I18n.GetCurrencies())
            {
                this.specimen_price_label.Text = currency;
                int tmp_widht = this.specimen_price_label.SizeRequest().Width;
                if (tmp_widht > width)
                    width = tmp_widht;
            }

            this.specimen_price_label.WidthRequest = (int)(width * GuiDesigner.ScaleFactor) + 3;
        }

        public Animation Animation { get; private set; }
        public GuiDesigner GuiDesigner { get; private set; }
        private ScrolledWindowSetter ScrolledWindow { get; set; }
    }
}
