// 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 System.Threading;
using Gtk;
using Hiperscan.I18n;
using Hiperscan.Spectroscopy;
using Hiperscan.Unix;
using Glade;


namespace Hiperscan.Extensions.ApoIdent
{
	public enum PdfLoadingState
	{
		Init,
		BeginLoadingValidationDoc,
		BeginLoadingSubstanceDoc,
		LoadingValidationDocFinished,
		LoadingSubstanceDocFinished,
		PdfsVisibleForUser,
	}
	
	public partial class FinderWindow
	{
        [Widget] Gtk.Dialog identmodule_info_dialog = null;

        private void CreateIdentServerClientInstance(Configurations config)
		{
			this.IdentServerClient = new IdentServerClient(config);

			this.IdentServerClient.DefaultConnectionFailed 		+= this.OnDefaultConnectionFailed;
			this.IdentServerClient.IdentModuleVersionRefused	+= this.OnIdentModuleVersionRefused;
			this.IdentServerClient.ConnectionRefused			+= this.OnConnectionRefused;
			
			this.IdentServerClient.RegistrationFailed			+= this.OnRegistrationFailed;
			this.IdentServerClient.OnNoReleaseVersion			+= this.OnNonReleased;

			this.IdentServerClient.RemindOfUpdate				+= this.OnRemindOfUpdate;
		}
		
		#region start server
        private void OnDefaultConnectionFailed(object sender, EventArgs e)
		{
            string info = Catalog.GetString("Cannot start Ident Module. This component is required to perform " + 
                                             "substance analyses on your computer locally. Please also check if a compatible version is installed.\n\n" +
                                             "In case you do not have a license for HiperScan IdentModule, please " +
                                             "contact our customer services for further information:\n" +
                                             "Email: kundenservice@apo-ident.de\nTelefon: +49 (0)351 212 496 33");

            bool dont_show_again = this.Config.GuiSettings.DontShowServerMessageAgain;
            if (dont_show_again == false)
            {
                this.HideGreetingWindow();
                this.host.ShowInfoMessage(this.finder_window, ref dont_show_again, info);
                this.Config.GuiSettings.DontShowServerMessageAgain = dont_show_again;
                this.ShowGreetingWindow();
            }

            this.Update(FinderUpdateState.IdentServerNotInitialized, info);
		}
		
        private void OnIdentModuleVersionRefused(object sender, EventArgs e)
		{
            string message = (string) (e as DataEventArgs).Data[DataEventArgs.ERROR];
                
			message = String.Format(Catalog.GetString("The connection to the Ident Module on \"{0}\" failed: {1}"),
					                          this.IdentServerClient.Address, message);
			
			message += ServiceForRepeatedError;	

            this.HideGreetingWindow();
			this.host.ShowInfoMessage(this.finder_window, message);
            this.Update(FinderUpdateState.IdentServerNotInitialized, message);
		}
		
        private void OnConnectionRefused(object sender, EventArgs e)
        {
            string message = (string) (e as DataEventArgs).Data[DataEventArgs.ERROR];

			message = String.Format(Catalog.GetString("The connection to the Ident-module on \"{0}\" failed: {1}"),
					                          this.IdentServerClient.Address, message);
			message += Catalog.GetString("\n" + 
					                             "Please check the connection settings in the preferences dialog. " + 
					                             "You can find these settings in the register \"Acouisition settings -> Identification\". " + 
					                             "After closing the preferences dialog the program tries to connect to the Ident Module " + 
					                             "or you can connect manually with a click on the button " + 
					                             "\"Connect\" below in the toolbar of the Apo-Ident surface");
			
			message += ServiceForRepeatedError;
            this.HideGreetingWindow();
			this.host.ShowInfoMessage(this.finder_window, message);
            this.Update(FinderUpdateState.IdentServerNotInitialized, message);
		}
		#endregion start server
		
		
		#region device registration
		private void OnRegistrationFailed(object sender, EventArgs e)
        {
            string message = (string) (e as DataEventArgs).Data[DataEventArgs.ERROR];
			
            try
			{
				message = String.Format(Catalog.GetString("The registration for device \"{0}\" failed: {1}"),
					this.Finder.Device.Info.SerialNumber, message);
			}
			catch(Exception)
			{
				message = String.Format(Catalog.GetString("The registration failed: {0}"), message);
			}
			
			message += ServiceForNoRepeatedError;

			this.HideGreetingWindow();
			this.host.ShowInfoMessage(this.finder_window, message);
            this.Update(FinderUpdateState.IdentServerNotInitialized, message);
		}
		#endregion

		private void OnBeginLoadingData(object sender, EventArgs e)
		{
			this.progressbar.Fraction = 0;
			this.progressbar.Visible = true;
			this.Update(FinderUpdateState.OnBeginLoadingData);
		}
		
        private void OnLoadingDatatProgressed(object sender, EventArgs e)
		{
            this.progressbar.Fraction = (double) (e as DataEventArgs).Data[DataEventArgs.PROGRESS];
			this.progressbar.QueueDraw();
			this.host.ProcessEvents();
		}

		
        private void OnLoadingDataFailed(object sender, EventArgs e)
		{
            string message = (string) (e as DataEventArgs).Data[DataEventArgs.ERROR];

			try
			{
				this.HideGreetingWindow();
				if (string.IsNullOrEmpty(message) == true)
				{
					message = String.Format(Catalog.GetString("There are no models available for this device. (Serial number {0})"), 
                                            this.Finder.Device.Info.SerialNumber);
				}
				else
				{
					message = String.Format(Catalog.GetString("Could not load models for this device. (Serial number {0}): {1}"), 
                                            this.Finder.Device.Info.SerialNumber, message);
				}
			}
			catch(Exception)
			{
				message = String.Format(Catalog.GetString("Could not load models for this device: {0}"), message);
			}
			message += FinderWindow.ServiceForNoRepeatedError;
            this.host.ShowInfoMessage(this.finder_window, message);

            this.Update(FinderUpdateState.LoadingSubstanceClassesFailed, message);
			
		}

        private void OnNonReleased(object sender, EventArgs e)
        {
            string message = (string) (e as DataEventArgs).Data[DataEventArgs.ERROR];

			this.HideGreetingWindow();
			message += FinderWindow.ServiceForNoRepeatedError;
			this.FinderAnimation.SetAnimation(AnimationType.Error);
			this.FinderAnimation.SetError(AnimationErrorType.NonReleasedIdentModule, message);
			this.host.ShowInfoMessage(this.finder_window, message);
		}
		
		private string Address
		{
			get
			{
				string current_server_address = String.Empty;
				switch(this.Config.AcquisitionSettings.IdentificationMode)
				{
				case IdentificationMode.Local:
					current_server_address = "localhost";
					break;
					
				case IdentificationMode.Custom:
					current_server_address = this.Config.AcquisitionSettings.Url;
					break;
					
				default:
					break;
				}
				return current_server_address;
			}
		}

		private int TcpPort
		{
			get
			{
				if (this.Config.AcquisitionSettings.IdentificationMode == IdentificationMode.Local)
                    return Spectroscopy.IdentModule.IdentServer.TCP_PORT;

				return this.Config.AcquisitionSettings.TcpPort;
			}
		}
		


		private void SetServer()
		{
			this.InitState = ServerDeviceState.None;
			this.InitializeDeviceAndIdentModule();
		}
			
		private void OnRemindOfUpdate(object sender, EventArgs e)
		{
			this.HideGreetingWindow();
			this.host.ProcessEvents();

            this.DontShowIdentModuleDialogAgain = false;

            Glade.XML gui = new Glade.XML(null, "ApoIdent.Resources.Glade.FinderWindow.glade", "identmodule_info_dialog", "Hiperscan");
            gui.Autoconnect(this);

            this.identmodule_info_dialog.SetWmclass(Plugin.name.ToLower(),
                                           Plugin.name.ToLower());

            this.identmodule_info_dialog.TransientFor = this.GtkWindow;
            this.identmodule_info_dialog.IconList = ApoIdentStock.FinderIcons;

            ResponseType response = (ResponseType)this.identmodule_info_dialog.Run();

            identmodule_info_dialog.Destroy();

            if (response == ResponseType.Apply)
                this.OpenIdentServerUrl();

            if (this.DontShowIdentModuleDialogAgain == true)
                this.Config.AcquisitionSettings.ReleaseExpirationTime = DateTime.Now.AddMonths(1);
		} 

        private void OpenIdentServerUrl()
        {
            try
            {
                System.Diagnostics.Process.Start(Urls.OnlineHelp(ReferrerId.IdentModuleUpdate, false));
            }
            catch (Exception ex)
            {
                string message = String.Format(Catalog.GetString("Cannot open link to Apo-Ident Service Center:{0}"),
                                               ex.Message);

                Gtk.MessageDialog mdlg = new MessageDialog(this.finder_window,
                                                           DialogFlags.Modal,
                                                           Gtk.MessageType.Error,
                                                           ButtonsType.Ok,
                                                           message);

                mdlg.IconList = ApoIdentStock.FinderIcons;
                mdlg.Run();
                mdlg.Destroy();
            }
        }

        private void OnIdentModuleInfoToggled(object sender, EventArgs e)
        {
            this.DontShowIdentModuleDialogAgain = (sender as Gtk.CheckButton).Active;
        }

        public IdentServerClient IdentServerClient { get; private set; }
        private bool DontShowIdentModuleDialogAgain { get; set; }
	}
}