// Created with MonoDevelop
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2023. 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.IO;

using Glade;

using Hiperscan.GtkExtensions.Widgets;
using Hiperscan.GtkExtensions.Compiler;
using Hiperscan.Extensions.ReferenceCheck.Control.Enums;
using Hiperscan.Extensions.ReferenceCheck.Control.GuiUpdate;
using Hiperscan.Extensions.ReferenceCheck.Control.Acquisition;
using Hiperscan.Extensions.ReferenceCheck.View.Resources.StatePictures;

namespace Hiperscan.Extensions.ReferenceCheck.View
{
    public partial class GUI
    {
        [Widget] Gtk.Alignment acquisition_alignment = null;
        [Widget] Gtk.Label acquisition_title_label = null;
        [Widget] Gtk.Label acquisition_advice_label = null;
        [Widget] Gtk.Image acquisition_image = null;
        [Widget] Gtk.Label acquisition_session_label = null;
        [Widget] Gtk.Label acquisition_session_out_label = null;
        [Widget] Gtk.Label acquisition_serial_label = null;
        [Widget] Gtk.Entry acquisition_entry = null;
        [Widget] Gtk.Button acquisition_button = null;
        [Widget] Gtk.EventBox acquisition_button_eventbox = null;
        [Widget] Gtk.Label acquisiiton_time_out_label = null;

        private void InitAcuisitionSection()
        {
            this.acquisition_title_label.Markup = this.GetLongestTitle();
            this.acquisition_advice_label.Text = this.GetLongestAdvice();

            this.AcquisitionSerialEntry = new OutLinedEntry(this.acquisition_entry);
            this.AcquisitionSerialEntry.IsValid = false;

            this.AcquisitionSerialEntry.ValueChanged += this.OnAcquisitionEntryValueChanged;
            this.AcquisitionSerialEntry.GtkEntry.Activated += this.OnAcquisitionEntryActivated;
            this.acquisition_button.Clicked += this.OnBlackAcquisitionButtonClicked;
        }

        private void OnAcquisitionEntryValueChanged(object sender, EventArgs e)
        {
            this.Control.CurrentAcquisitionSet.SetSerial(this.AcquisitionSerialEntry.GtkEntry.Text);
        }

        private void OnAcquisitionEntryActivated(object sender, EventArgs e)
        {
            this.Control.AcquireSpectrum();
        }

        private void OnBlackAcquisitionButtonClicked(object sender, EventArgs e)
        {
            this.Control.AcquireSpectrum();
        }

        private void UpdateAcquisitionSection(UpdateCategory category)
        {
            if (category.HasFlag(UpdateCategory.Sensitives))
            {
                bool is_waiting = this.Control.CurrentAcquisitionSet.IsWaitingForInput;

                this.acquisition_session_label.Sensitive = is_waiting;
                this.acquisition_session_out_label.Sensitive = is_waiting;
                this.acquisition_advice_label.Sensitive = is_waiting;
                this.acquisition_serial_label.Sensitive = is_waiting;

                this.AcquisitionSerialEntry.GtkEntry.Sensitive = is_waiting;
                this.AcquisitionSerialEntry.GtkEntry.IsEditable = is_waiting;

                bool can_acqure = this.Control.CurrentAcquisitionSet.CanAcquire;
                this.acquisition_button.Sensitive = can_acqure;
                this.acquisition_button_eventbox.ModifyBg(Gtk.StateType.Normal,
                    can_acqure ? new Gdk.Color(50, 205, 50) : new Gdk.Color(232, 232, 232));
            }

            if (category.HasFlag(UpdateCategory.QuickDataChange))
            {
                this.AcquisitionSerialEntry.GtkEntry.Text = this.Control.CurrentAcquisitionSet.Serial;
                this.AcquisitionSerialEntry.IsValid = this.Control.CurrentAcquisitionSet.IsSerialValid;
                this.AcquisitionSerialEntry.GtkEntry.IsEditable = this.Control.CurrentAcquisitionSet.AllowSerialInput;
                this.AcquisitionSerialEntry.Sensitive = this.Control.CurrentAcquisitionSet.AllowSerialInput;
                this.acquisition_session_out_label.Text = this.Control.CurrentAcquisitionSet.SessionOutput;
            }

            if (category.HasFlag(UpdateCategory.SlowDataChange))
            {
                if (this.Control.CurrentAcquisitionSet.IsWaitingForInput)
                    this.AcquisitionSerialEntry.GtkEntry.HasFocus = true;

                this.acquisition_title_label.Markup = String.Format("<span size=\"large\"><b>{0}</b></span>",
                                                                    this.Control.CurrentAcquisitionSet.TitleMessage);

                this.acquisition_advice_label.Text = this.Control.CurrentAcquisitionSet.AdviceMessage;

                this.SetAcquisitionImage();
            }

            if (category.HasFlag(UpdateCategory.Often))
            {
                this.acquisiiton_time_out_label.Text = this.Control.AcqquisitionTime;
            }
        }

        private void SetAcquisitionImage()
        {
            if (this.Control.IsInternalRecalibrating)
            {
                this.acquisition_image.Pixbuf = this.AcquisitionPictures[AcquisitionPicture.InternalRecalibration];
            }
            else
            {
                bool is_acuiring = this.Control.CurrentAcquisitionSet.IsAcquiring;

                switch (this.Control.CurrentAcquisitionSet.AcquisitionType)
                {
                    case AcquisitionType.Black:
                        if (is_acuiring)
                            this.acquisition_image.Pixbuf = this.AcquisitionPictures[AcquisitionPicture.MeasuringBlackReference];
                        else
                            this.acquisition_image.Pixbuf = this.AcquisitionPictures[AcquisitionPicture.ReadyForBlackReference];
                        break;

                    case AcquisitionType.White:
                        if (is_acuiring)
                            this.acquisition_image.Pixbuf = this.AcquisitionPictures[AcquisitionPicture.MeasuringWhiteReference];
                        else
                            this.acquisition_image.Pixbuf = this.AcquisitionPictures[AcquisitionPicture.ReadyForWhiteReference];
                        break;

                    case AcquisitionType.WhiteInsert:
                        if (is_acuiring)
                            this.acquisition_image.Pixbuf = this.AcquisitionPictures[AcquisitionPicture.MeasuringWhiteInsertReference];
                        else
                            this.acquisition_image.Pixbuf = this.AcquisitionPictures[AcquisitionPicture.ReadyForWhiteInsertReference];
                        break;

                    case AcquisitionType.Empty:
                        if (is_acuiring)
                            this.acquisition_image.Pixbuf = this.AcquisitionPictures[AcquisitionPicture.MeasuringEmptyReference];
                        else
                            this.acquisition_image.Pixbuf = this.AcquisitionPictures[AcquisitionPicture.ReadyForEmptyReference];
                        break;

                    case AcquisitionType.Transflectance:
                        if (this.Control.IsFinderSD)
                        {
                            if (is_acuiring)
                                this.acquisition_image.Pixbuf = this.AcquisitionPictures[AcquisitionPicture.MeasuringTransflectanceAu];
                            else
                                this.acquisition_image.Pixbuf = this.AcquisitionPictures[AcquisitionPicture.ReadyForTransflectanceAu];
                        }
                        else
                        {
                            if (is_acuiring)
                                this.acquisition_image.Pixbuf = this.AcquisitionPictures[AcquisitionPicture.MeasuringTransflectance];
                            else
                                this.acquisition_image.Pixbuf = this.AcquisitionPictures[AcquisitionPicture.ReadyForTransflectance];
                        }
                        break;

                    default:
                        break;
                }
            }
        }

        private string GetLongestTitle()
        {
            string longest_text = String.Empty;
            double width = 0;

            foreach (AcquisitionType acquisistio_type in Enum.GetValues(typeof(AcquisitionType)))
            {
                string tmp_title = AcquisitionSet.GetTitle(acquisistio_type);
                GraphicsText tmp_graphic = new GraphicsText();
                tmp_graphic.Text = tmp_title;
                double tmp_width = MonoCairoGraphicCompiler.MeasureGraphicsText(tmp_graphic).Width;

                if (tmp_width > width)
                {
                    width = tmp_width;
                    longest_text = tmp_title;
                }
            }

            return longest_text;
        }

        private string GetLongestAdvice()
        {
            string longest_text = String.Empty;
            double width = 0;

            foreach (AcquisitionType acquisistio_type in Enum.GetValues(typeof(AcquisitionType)))
            {
                string tmp_title = AcquisitionSet.GetAdvice(acquisistio_type, true);
                GraphicsText tmp_graphic = new GraphicsText();
                tmp_graphic.Text = tmp_title;
                double tmp_width = MonoCairoGraphicCompiler.MeasureGraphicsText(tmp_graphic).Width;

                if (tmp_width > width)
                {
                    width = tmp_width;
                    longest_text = tmp_title;
                }
            }

            return longest_text;
        }

        private OutLinedEntry AcquisitionSerialEntry { get; set; }
    }
}
