// 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 Hiperscan.GtkExtensions.StandardDialogs;
using Hiperscan.GuiExtensions;
using Hiperscan.GuiExtensions.Dialog;

namespace Hiperscan.GtkExtensions.GuiSync
{
    public abstract class GuiSynchronizerTemplate<T, U, V> 
                    where T : SyncControlTemplate<U, V>
                    where U : UpdateArgsTemplate<V>
                    where V : DialogArgsTempleate                                                           
                                                         
    {
        protected abstract void OtherUpdates(U args);
        protected abstract void InitGuiSyncControl(Gtk.Window main_window, T sync_control);

        public void Update(U args)
        {
            this.SyncControl.EnterUpdateGui(args);

            if (MainThread.ID < 0)
                throw new Exception("MainThread.ID is not set.");

            if (System.Threading.Thread.CurrentThread.ManagedThreadId == MainThread.ID)
                this.UpdateInMainThread(args, EventArgs.Empty);
            else
                Gtk.Application.Invoke((sender, e) => this.UpdateInMainThread(args, EventArgs.Empty));

            this.SyncControl.WaitForUpdateGuiFinished(args);
        }

        protected void UpdateInMainThread(object sender, EventArgs e)
        {
            U args = (U)sender;

            if (args.CursorState != CursorState.None)
                Cursor.UpdateCursor(this.MainWindow, args.CursorState);

            this.OtherUpdates(args);

            if (args.DialogArgs.StandardDialogType != StandardDialogType.None)
                StandardDialog.ShowStandardDialog(this.MainWindow, args.DialogArgs);

            this.SyncControl.LeaveUpdateGui(args);
        }

        public Gtk.Window MainWindow { get; protected set; }
        protected T SyncControl { get; set; }
    }
}
