// 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.Collections.Generic;

using Glade;

using Hiperscan.GtkExtensions.GuiSync;
using Hiperscan.Extensions.ReferenceCheck.Control;
using Hiperscan.Extensions.ReferenceCheck.Control.Enums;
using Hiperscan.Extensions.ReferenceCheck.Control.GuiUpdate;
using Hiperscan.Extensions.ReferenceCheck.View.Resources.StatePictures;

namespace Hiperscan.Extensions.ReferenceCheck.View
{
    public partial class GUI
    {
        [Widget] Gtk.Window main_window = null;
        [Widget] Gtk.Label main_version_output_label = null;
        [Widget] Gtk.Image main_image = null;
        [Widget] Gtk.EventBox next_button_eventbox = null;

        public static void Run(IHost host)
        {
            MainThread.ID = System.Threading.Thread.CurrentThread.ManagedThreadId;
            GUI gui = new GUI();
            gui.InitializeMainWindow(host);
        }

        private void InitializeMainWindow(IHost host)
        {
            this.Control = new CoreApp(host);
            this.Control.UpdateGuiNeeded += (update_arg) => this.Update(update_arg);

            this.HostWindow = host.MainWindow;

            Glade.XML gui = new Glade.XML(null, "Hiperscan.Extensions.ReferenceCheck.View.Resources.gui.glade", "main_window", null);
            gui.Autoconnect(this);

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

            this.MainWindow.Opacity = 0;
            this.InitMainSection();
            this.InitAcuisitionPictures();
            this.InitExecutionModeSection();
            this.InitSessionSection();
            this.InitDeviceSection();
            this.InitAcuisitionSection();
            this.InitRestoreSection();
            this.InitProtocolSection();

            this.MainWindow.ShowAll();
            this.SetWindowSize();

            this.MainWindow.KeyPressEvent += this.OnKeyPressed;
            this.MainWindow.FocusInEvent += this.OnMainWindowScanFocusedIn;
            this.MainWindow.FocusOutEvent += this.OnMainWindowScanFocusedOut;
            this.MainWindow.AllowGrow = false;
            this.MainWindow.AllowShrink = false;

            this.Control.CurrentVisibleView = ViewTypes.Password;

            this.MainWindow.Opacity = 1;
            this.MainWindow.SetPosition(Gtk.WindowPosition.CenterAlways);
            this.HostWindow.Visible = false;

            UpdateArgs arg = new UpdateArgs();
            arg.ViewType = ViewTypes.Password;
            arg.UpdateCatecory = UpdateCategory.All;
            this.Update(arg);
        }

        private void InitMainSection()
        {
            this.main_image.Pixbuf = new Gdk.Pixbuf(null, "Hiperscan.Extensions.ReferenceCheck.View.Resources.logo.png", 150, 100);
            this.main_version_output_label.Text = CoreApp.Version;
        }

        private void SetWindowSize()
        {
            this.Views.Add(ViewTypes.Password, this.password_alignment);
            this.Views.Add(ViewTypes.ExecutionMode, this.execution_mode_alignment);
            this.Views.Add(ViewTypes.Session, this.session_alignment);
            this.Views.Add(ViewTypes.InitDevice, this.device_init_alignment);
            this.Views.Add(ViewTypes.Acquisition, this.acquisition_alignment);
            this.Views.Add(ViewTypes.Protocol, this.protocol_alignment);
            this.Views.Add(ViewTypes.Restore, this.restore_alignment);

            int max_width = 0;
            int max_height = 0;

            foreach (Gtk.Alignment item in this.Views.Values)
            {
                int tmp_width = item.Allocation.Width;
                int tmp_height = item.Allocation.Height;
                if (tmp_width > max_width)
                    max_width = tmp_width;
                if (tmp_height > max_height)
                    max_height = tmp_height;

                item.Visible = false;
                item.NoShowAll = true;
            }

            foreach (Gtk.Alignment item in this.Views.Values)
            {
                item.WidthRequest = max_width;
                item.HeightRequest = max_height;
            }

            this.acquisition_advice_label.WidthRequest = this.acquisition_advice_label.Allocation.Height;
            this.acquisition_title_label.WidthRequest = this.acquisition_title_label.Allocation.Width;
        }

        private void InitAcuisitionPictures()
        {
            string resource = "Hiperscan.Extensions.ReferenceCheck.View.Resources.StatePictures.";
            foreach (AcquisitionPicture item in Enum.GetValues(typeof(AcquisitionPicture)))
                this.AcquisitionPictures.Add(item, new Gdk.Pixbuf(null, resource + item.ToString() + ".png", 135, 135));
        }

        private void OnMainWindowScanFocusedIn(object sender, EventArgs args)
        {
            this.Control.IsTopLevelWindow = true;
        }

        private void OnMainWindowScanFocusedOut(object sender, EventArgs args)
        {
            this.Control.IsTopLevelWindow = false;
        }

        private void OnNextButtonClicked(object sender, EventArgs e)
        {
            this.Control.SetNextView();
        }

        private void OnDeleteEvent(object sender, Gtk.DeleteEventArgs e)
        {
            this.Control.TryToExit();
            e.RetVal = true;
        }

        [GLib.ConnectBefore]
        private void OnKeyPressed(object sender, Gtk.KeyPressEventArgs e)
        {
            switch (e.Event.Key)
            {
                case Gdk.Key.Escape:
                    this.Control.TryToExit();
                    break;

                case Gdk.Key.KP_Enter:
                case Gdk.Key.Return:
                    if (this.Control.CurrentVisibleView == ViewTypes.Session)
                    {
                        if (this.black_spinbutton.HasFocus)
                            return;

                        if (this.white_spinbutton.HasFocus)
                            return;

                        if (this.transflectance_spinbutton.HasFocus)
                            return;

                        if (this.insert_spinbutton.HasFocus)
                            return;
                    }

                    if (this.Control.CanNext() == false)
                        return;

                    this.Control.SetNextView();
                    e.RetVal = true;
                    break;

                default:
                    break;
            }
        }

        private void Exit()
        {
            this.MainWindow.Destroy();
            this.HostWindow.Visible = true;
        }

        private CoreApp Control { get; set; }
        private Dictionary<ViewTypes, Gtk.Alignment> Views { get; set; } = new Dictionary<ViewTypes, Gtk.Alignment>();

        private Gtk.Window HostWindow { get; set; }
        private Dictionary<AcquisitionPicture, Gdk.Pixbuf> AcquisitionPictures { get; set; } = new Dictionary<AcquisitionPicture, Gdk.Pixbuf>();
    }
}
