// Created with MonoDevelop
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2018 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 Glade;
using Hiperscan.Unix;


namespace Hiperscan.Extensions.ApoIdent
{
    public enum WindowSections
    {
        ConfigSection,
        SubstanceSection,
        ResultSection,
        DetailSection,
    }

    public enum FinderUpdateState
    {
        StartIdentServerAndDevice,
        IdentServerNotInitialized,
        StartDeviceFailed,
        LoadingSubstanceClassesFailed,
        DeviceWarmupFailed,
        StartIdentServerAndDeviceSuccess,


        ResetAfterSubstanceChanged,
        SubstanceNotMeasurableChanged,
        SubstanceChangedFromExtern,

        BeforeClassifierSelectionShown,
        AfterEditingUserDefinedSubstances,

        BeginConfigComboChanged,
        EndConfigProfileChanged,
        ConfigProfileSettingsChanged,
        ConfigPrinterSettingsChanged,

        ExpiryDateChanged,
        AdditionalTestChanged,

        ConnectionLost,

        PreferencesClosed,

        OnBeginLoadingData,
        OnPdfDataChanged,

        AveragingSet,

        AfterLeavingBlindClassification,
      

        EmptyDieMeasurementBegin,
        EmptyDieMeasurementEnd,
        EmptyDieMeasurementFailedEnd,
        EmptyDieClassificationMeasurementEnd,

        MeasurementBegin,
        InternalCalibration,
        ExternalCalibration,
        MeasurementEnd,
        MeasurementFailedEnd,

        FinderChanged,
        ReportChanged,


        ReportSaved,
        ReportSavedFailed,
        AfterReportSaving,

        DeviceStateChanged,
        DeviceReadyChanged,
        DevicePollFinderButton,
        DeviceResetReference,
        DeviceRemoved,
        DeviceAfterInternalCalibration,
        DeviceAfterExternalCalibration,
    }

    public partial class FinderWindow
    {
        [Widget] Gtk.Window license_window = null;
        [Widget] Gtk.TextView license_textview = null;

        [Widget] Gtk.Window finder_window = null;
        [Widget] Gtk.Toolbar lhs_toolbar = null;
        [Widget] Gtk.Toolbar main_toolbar = null;

        [Widget] Gtk.Viewport main_viewport = null;
        [Widget] Gtk.Viewport tool_design_viewport = null;
        [Widget] Gtk.Viewport tool_viewport = null;
        [Widget] Gtk.Viewport status_viewport = null;
        [Widget] Gtk.Viewport design_top_viewport = null;
        [Widget] Gtk.Viewport design_bottom_viewport = null;
        [Widget] Gtk.Viewport design_left_viewport = null;
        [Widget] Gtk.Viewport design_right_viewport = null;
        [Widget] Gtk.Viewport scroll_viewport = null;

        [Widget] Gtk.Table finder_table = null;
        [Widget] Gtk.Table main_table = null;

        [Widget] Gtk.Alignment animation_align = null;
        [Widget] Gtk.Alignment main_alignment = null;
        [Widget] Gtk.Button design_button = null;
        [Widget] Gtk.DrawingArea design_drawingarea = null;

        [Widget] Gtk.Statusbar statusbar = null;
        [Widget] Gtk.ProgressBar progressbar = null;
        [Widget] Gtk.ScrolledWindow main_scrolledwindow = null;


        private void SetButtonStyle(WindowSections section, bool active)
        {
            switch (section)
            {
                case WindowSections.ConfigSection:
                    this.ModifyButton(this.config_label_button, active);
                    break;

                case WindowSections.SubstanceSection:
                    this.ModifyButton(this.class_label_button, active);
                    this.ModifyButton(this.substance_name_label_button, active);
                    this.ModifyButton(this.latin_name_label_button, active);
                    this.ModifyButton(this.substance_search_label_button, active);
                    break;

                case WindowSections.ResultSection:
                    this.ModifyButton(this.name_label_button, active);
                    break;

                case WindowSections.DetailSection:
                    this.ModifyButton(this.user_name_label_button, active);
                    this.ModifyButton(this.manufacturer_label_button, active);
                    this.ModifyButton(this.batch_number_button, active);
                    this.ModifyButton(this.comment_label_button, active);
                    this.ModifyButton(this.pzn_label_button, active);
                    this.ModifyButton(this.test_id_label_button, active);
                    this.ModifyButton(this.init_corr_factor_label_button, active);
                    break;

                default:
                    break;
            }
        }

        private void ModifyButton(Button b, bool active)
        {
            try
            {
                if (this.color_init == false)
                {
                    this.InactiveColor = b.Style.Foreground(StateType.Insensitive);
                    this.ActiveColor = b.Style.Foreground(StateType.Normal);
                    this.color_init = true;
                }

                b.Child.ModifyFg(StateType.Insensitive, active == true ? this.ActiveColor : this.InactiveColor);
            }
            catch (NullReferenceException ex)
            {
                Console.WriteLine("Error in ModifyButton(): " + ex.Message);
            }
        }

        private bool color_init = false;
        private Gdk.Color InactiveColor { get; set; }
        private Gdk.Color ActiveColor { get; set; }

        private void ResetLinkButons()
        {
            string tmp = null;
            tmp = this.nir_result_linkbutton.Uri;
            this.nir_result_linkbutton.Uri = String.Empty;
            this.nir_result_linkbutton.Uri = tmp;

            tmp = this.rating_linkbutton.Uri;
            this.rating_linkbutton.Uri = String.Empty;
            this.rating_linkbutton.Uri = tmp;

            tmp = this.validation_linkbutton.Uri;
            this.validation_linkbutton.Uri = String.Empty;
            this.validation_linkbutton.Uri = tmp;

            tmp = this.additional_linkbutton.Uri;
            this.additional_linkbutton.Uri = String.Empty;
            this.additional_linkbutton.Uri = tmp;

            tmp = this.use_by_date_linkbutton.Uri;
            this.use_by_date_linkbutton.Uri = String.Empty;
            this.use_by_date_linkbutton.Uri = tmp;

            tmp = this.detection_rate_linkbutton.Uri;
            this.detection_rate_linkbutton.Uri = String.Empty;
            this.detection_rate_linkbutton.Uri = tmp;
        }

        public void Update(FinderUpdateState status)
        {
            this.Update(status, String.Empty);
        }

        public void Update(FinderUpdateState status, string message)
        {
            this.IsUpdating = true;
            try
            {
                this.UpdateAnimation(status, message);

                switch (status)
                {
                    //=========init================================
                    case FinderUpdateState.StartIdentServerAndDevice:
                        this.Busy = true;
                        break;

                    case FinderUpdateState.IdentServerNotInitialized:
                    case FinderUpdateState.StartDeviceFailed:
                    case FinderUpdateState.LoadingSubstanceClassesFailed:
                        this.UpdateMenueSection(true);
                        this.UpdateConfigSection();
                        this.UpdateSubstanceSection(true);
                        this.UpdateMeasurementSection();
                        this.UpdateResultSection();
                        this.UpdateDetailSection(false);
                        this.UpdateReportSection(false);
                        this.progressbar.Visible = false;
                        this.Busy = false;
                        break;

                    case FinderUpdateState.StartIdentServerAndDeviceSuccess:
                        this.UpdateMenueSection(true);
                        this.UpdateConfigSection();
                        this.UpdateSubstanceSection(true);
                        this.UpdateMeasurementSection();
                        this.UpdateResultSection();
                        this.UpdateDetailSection(false);
                        this.UpdateReportSection(false);
                        this.progressbar.Visible = false;
                        this.UpdateStatusbarSection();
                        this.Busy = false;
                        this.FocusSpecimenSearchEntry();
                        break;

                    case FinderUpdateState.DeviceWarmupFailed:
                        this.UpdateMenueSection(true);
                        this.UpdateConfigSection();
                        this.UpdateSubstanceSection(true);
                        this.UpdateMeasurementSection();
                        this.UpdateResultSection();
                        this.UpdateDetailSection(false);
                        this.UpdateReportSection(false);
                        this.progressbar.Visible = false;
                        this.UpdateStatusbarSection();
                        this.progressbar.Visible = false;
                        this.Busy = false;
                        break;


                    /*============== changes protocol ===========================================*/
                    case FinderUpdateState.ExpiryDateChanged:
                        this.UpdateMenueSection(false);
                        this.UpdateDetailSection(false, false);
                        this.UpdateReportSection(false);
                        break;

                    case FinderUpdateState.AdditionalTestChanged:
                        this.UpdateMenueSection(false);
                        this.UpdateDetailSection(false, false);
                        this.UpdateReportSection(false);
                        break;

                    case FinderUpdateState.ReportChanged:
                        this.UpdateMenueSection(false);
                        this.UpdateReportSection(false);
                        break;

                    case FinderUpdateState.ConnectionLost:
                        this.UpdateMenueSection(true);
                        this.UpdateConfigSection();
                        this.UpdateSubstanceSection(true);
                        this.UpdateMeasurementSection();
                        this.UpdateResultSection();
                        this.UpdateDetailSection(false);
                        this.UpdateReportSection(false);
                        this.progressbar.Visible = false;
                        this.Busy = false;
                        break;

                    case FinderUpdateState.ReportSaved:
                        this.UpdateMenueSection(false);
                        this.UpdateReportSection(true);
                        break;

                    /*==============Changes in Substancessection===========================================*/
                    case FinderUpdateState.OnBeginLoadingData:
                        this.UpdateSubstanceSection(false);
                        break;

                    case FinderUpdateState.BeforeClassifierSelectionShown:
                        this.UpdateSubstanceSection(false);
                        break;

                    case FinderUpdateState.ResetAfterSubstanceChanged:
                        this.UpdateMenueSection(false);
                        this.UpdateSubstanceSection(false);
                        this.UpdateMeasurementSection();
                        this.UpdateResultSection();
                        this.UpdateDetailSection(true);
                        this.UpdateReportSection(false);
                        break;

                    case FinderUpdateState.SubstanceNotMeasurableChanged:
                        this.UpdateMenueSection(false);
                        this.UpdateSubstanceSection(false);
                        this.UpdateMeasurementSection();
                        this.UpdateResultSection();
                        this.UpdateDetailSection(false);
                        this.UpdateReportSection(false);
                        break;

                    case FinderUpdateState.SubstanceChangedFromExtern:
                        this.UpdateDetailSection(false);
                        break;

                    case FinderUpdateState.OnPdfDataChanged:
                        this.UpdateMenueSection(true);
                        break;

                    case FinderUpdateState.BeginConfigComboChanged:
                        this.Busy = true;
                        break;

                    case FinderUpdateState.EndConfigProfileChanged:
                        this.UpdateConfigSection();
                        this.UpdateMenueSection(false);
                        this.UpdateSubstanceSection(true);
                        this.UpdateMeasurementSection();
                        this.UpdateResultSection();
                        this.UpdateDetailSection(false);
                        this.UpdateReportSection(false);
                        this.FocusSpecimenSearchEntry();
                        this.Busy = false;
                        break;

                    case FinderUpdateState.ConfigProfileSettingsChanged:
                        this.UpdateConfigSection();
                        this.UpdateSubstanceSection(false);
                        this.UpdateDetailSection(false);
                        break;


                    case FinderUpdateState.ConfigPrinterSettingsChanged:
                        this.UpdateSubstanceSection(false);
                        this.UpdateDetailSection(false);
                        break;

                    case FinderUpdateState.AfterEditingUserDefinedSubstances:
                        this.UpdateMenueSection(false);
                        this.UpdateSubstanceSection(true);
                        this.UpdateMeasurementSection();
                        this.UpdateResultSection();
                        this.UpdateDetailSection(false);
                        this.UpdateReportSection(false);
                        break;

                    /*==============Changes in EmptyDieMeasurementsection=================================*/
                    case FinderUpdateState.EmptyDieMeasurementBegin:
                        this.UpdateMenueSection(false);
                        this.UpdateResultSection();
                        this.UpdateDetailSection(false);
                        this.Busy = true;
                        break;

                    case FinderUpdateState.EmptyDieMeasurementEnd:
                        this.UpdateMenueSection(false);
                        this.UpdateMeasurementSection();
                        this.UpdateResultSection();
                        this.UpdateDetailSection(false);
                        this.UpdateReportSection(false);
                        this.Busy = false;
                        break;

                    case FinderUpdateState.EmptyDieMeasurementFailedEnd:
                        this.UpdateMenueSection(false);
                        this.UpdateMeasurementSection();
                        this.UpdateResultSection();
                        this.UpdateDetailSection(false);
                        this.UpdateReportSection(false);
                        this.Busy = false;
                        break;

                    case FinderUpdateState.EmptyDieClassificationMeasurementEnd:
                        this.UpdateMenueSection(false);
                        this.UpdateMeasurementSection();
                        this.UpdateResultSection();
                        this.UpdateDetailSection(false);
                        this.UpdateReportSection(false);
                        this.Busy = false;
                        break;

                    /*==============Changes in Measurementsection=========================================*/
                    case FinderUpdateState.MeasurementBegin:
                        this.UpdateMenueSection(false);
                        this.UpdateResultSection();
                        this.UpdateDetailSection(false);
                        this.Busy = true;
                        break;

                    case FinderUpdateState.MeasurementEnd:
                        this.UpdateMenueSection(false);
                        this.UpdateMeasurementSection();
                        this.UpdateResultSection();
                        this.UpdateDetailSection(false);
                        this.UpdateReportSection(false);
                        this.Busy = false;
                        this.SetFocusAfterMeasurement();
                        break;

                    case FinderUpdateState.MeasurementFailedEnd:
                        this.UpdateMenueSection(false);
                        this.UpdateMeasurementSection();
                        this.UpdateResultSection();
                        this.UpdateDetailSection(false);
                        this.UpdateReportSection(false);
                        this.Busy = false;
                        this.SetFocusAfterMeasurement();
                        break;

                    /*==============Changes in Preferences || Detailsection || Reportsection==============*/
                    case FinderUpdateState.PreferencesClosed:
                        this.UpdateConfigSection();
                        break;

                    /*==============Changes in Statusbar==================================================*/
                    case FinderUpdateState.DeviceStateChanged:
                        this.UpdateStatusbarSection();
                        this.UpdateMenueSection(false);
                        break;

                    /*==============Changes in Device=====================================================*/
                    case FinderUpdateState.DeviceReadyChanged:
                        this.UpdateMenueSection(false);
                        this.UpdateSubstanceSection(false);
                        this.UpdateMenueSection(false);
                        this.UpdateMeasurementSection();
                        this.UpdateReportSection(false);
                        break;

                    case FinderUpdateState.DeviceResetReference:
                        this.UpdateMenueSection(false);
                        this.UpdateMeasurementSection();
                        break;

                    case FinderUpdateState.DevicePollFinderButton:
                        this.UpdateMeasurementSection();
                        break;

                    case FinderUpdateState.DeviceRemoved:
                        this.UpdateMenueSection(false);
                        this.UpdateSubstanceSection(false);
                        this.UpdateMeasurementSection();
                        this.UpdateResultSection();
                        this.UpdateDetailSection(false);
                        this.UpdateReportSection(false);
                        break;

                    case FinderUpdateState.DeviceAfterInternalCalibration:
                        this.UpdateMeasurementSection();
                        break;

                    case FinderUpdateState.AveragingSet:
                    case FinderUpdateState.DeviceAfterExternalCalibration:
                        this.UpdateMenueSection(false);
                        this.UpdateMeasurementSection();
                        break;

                    case FinderUpdateState.FinderChanged:
                        this.UpdateMenueSection(false);
                        break;

                    case FinderUpdateState.AfterLeavingBlindClassification:
                        this.UpdateMenueSection(false);
                        this.UpdateMeasurementSection();
                        break;
                }
            }
            catch (Exception ex)
            {
                if (ApoIdentEnvs.DebugOn)
                    this.host.ShowInfoMessage(this.finder_window, ex.ToString());
                Console.WriteLine(ex.ToString());
            }

            this.IsUpdating = false;

            if (this.Busy == true)
                this.host.ProcessEvents();
        }

        private void UpdateStatusbarSection()
        {
            uint id = this.statusbar.GetContextId("DeviceState");
            this.statusbar.Pop(id);
            this.statusbar.Push(id, Catalog.GetString("Device state:") + " " + this.Finder.DeviceMode);
        }

        private void SetScrolledWindow()
        {
            Requisition desired_size = this.finder_window.SizeRequest();
            int width = (int)((this.finder_window.Screen.Width / this.finder_window.Screen.NMonitors) * 0.9);
            int height = (int)((this.finder_window.Screen.Height) * 0.9);

            bool do_maximize = false;
            if (this.main_scrolledwindow.HscrollbarPolicy == PolicyType.Never)
            {
                if (desired_size.Width > width)
                {
                    do_maximize = true;
                }
            }

            if (this.main_scrolledwindow.VscrollbarPolicy == PolicyType.Never)
            {
                if (desired_size.Height > height)
                    do_maximize = true;
            }

            if (do_maximize == true)
            {
                this.finder_window.Maximize();
                this.main_scrolledwindow.HscrollbarPolicy = PolicyType.Automatic;
                this.main_scrolledwindow.VscrollbarPolicy = PolicyType.Automatic;

                Gdk.Color light_red_view = new Gdk.Color(255, 45, 45);
                if (EnvironmentInfo.OS == OperatingSystem.Windows)
                    this.scroll_viewport.ModifyBg(StateType.Normal, light_red_view);

                this.main_alignment.Xscale = 1;
            }
        }

        private void OnWindowStateChanged(object sender, EventArgs e)
        {
            if (this.finder_window.GdkWindow.State == Gdk.WindowState.Maximized)
                this.Config.GuiSettings.WindowMaximized = true;
            else
                this.Config.GuiSettings.WindowMaximized = false;
        }

        private void SetBusyState()
        {
            if (this.Busy == true)
            {
                this.SetWatchCursor();
                this.SetButtonStyle(WindowSections.SubstanceSection, false);
                this.SetButtonStyle(WindowSections.ResultSection, false);
                this.SetButtonStyle(WindowSections.DetailSection, false);
                this.SetButtonStyle(WindowSections.ConfigSection, false);
            }
            else
            {
                this.PollFinderButton = false;
                this.HideGreetingWindow();
                this.SetArrowCursor();
                bool active = this.InitState == ServerDeviceState.Success;
                this.SetButtonStyle(WindowSections.SubstanceSection, active);
                this.SetButtonStyle(WindowSections.ConfigSection, true);
            }

            this.GtkWindow.Sensitive = this.Busy == false;
        }

        private void SetWatchCursor()
        {
            if (this.finder_window.IsRealized == false)
                return;

            this.finder_window.GdkWindow.Cursor = new Gdk.Cursor(Gdk.CursorType.Watch);
        }

        private void SetArrowCursor()
        {
            if (this.finder_window.IsRealized == false)
                return;

            this.finder_table.Sensitive = true;
            this.lhs_toolbar.Sensitive = true;
            this.finder_window.GdkWindow.Cursor = new Gdk.Cursor(Gdk.CursorType.Arrow);
        }



        public string GtkUsernameValue
        {
            get { return StringHelper.CleanUserInputString(this.user_regexentry.Entry.Text); }
            set { this.user_regexentry.Entry.Text = StringHelper.CleanUserInputString(value); }
        }

        public string GtkSupplierValue
        {
            get { return StringHelper.CleanUserInputString(this.supplier_regexentry.Entry.Text); }
            set { this.supplier_regexentry.Entry.Text = StringHelper.CleanUserInputString(value); }
        }

        public string GtkBatchValue
        {
            get { return StringHelper.CleanUserInputString(this.batch_regexentry.Entry.Text); }
            set { this.batch_regexentry.Entry.Text = StringHelper.CleanUserInputString(value); }
        }

        public string GtkPznValue
        {
            get { return StringHelper.CleanUserInputString(this.pzn_regexentry.Entry.Text); }
            set { this.pzn_regexentry.Entry.Text = StringHelper.CleanUserInputString(value); }
        }

        public string GtkCommentValue
        {
            get { return StringHelper.CleanUserInputString(this.comment_regentry.Entry.Text); }
            set { this.comment_regentry.Entry.Text = StringHelper.CleanUserInputString(value); }
        }

        public string GtkCorrectionFactorValue
        {
            get { return StringHelper.CleanUserInputString(this.corr_fac_regexentry.Entry.Text); }
            set { this.corr_fac_regexentry.Entry.Text = StringHelper.CleanUserInputString(value); }
        }

        public string GtkUseByDateLabelValue
        {
            get
            {
                return this.use_by_date_linkbutton.Label;
            }
        }

        public int DeadLineYear
        {
            get
            {
                return Int32.Parse(this.expiry_date_year_combo.ActiveText);
            }
        }

        public int DeadLineMonth
        {
            get
            {
                return this.expiry_date_month_combo.Active;
            }
        }

        private string OldBatchNumber { get; set; }
        private Animation FinderAnimation { get; set; }
        private bool IsUpdating { get; set; }

        public static Gtk.Window ParentWindow 
        {
            get
            {
                return FinderWindow.current_instance.GtkWindow;
            }
        }
                         
                         
                         
                         
    }
}

