// 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 System.Runtime.InteropServices;
using Gtk;
using Glade;


namespace Hiperscan.Extensions.ApoIdent
{

	public static class TouchscreenMode
	{
		private enum ScrollState
		{ 
			Top,
			Bottom,
			Undefined
		}
		
		public static ScrolledWindow ScrolledWindow { get; set; }
		public static bool OnscreenKeyboardVisible  { get; set; }
		public static int DefaultWindowHeight       { get; set; }
		public static FinderWindow FinderWindow     { get; set; }
		public static Viewport Viewport             { get; set; }

		private static bool _osk_visible = false;
		private static ScrollState scroll_state = ScrollState.Undefined;
		
		[return: MarshalAs(UnmanagedType.Bool)]
		[DllImport("user32.dll", SetLastError = true)]
		static extern bool PostMessage(IntPtr hWnd, uint Msg, UIntPtr wParam, IntPtr lParam);

		[DllImport("user32.dll", CharSet = CharSet.Unicode)]
		static extern IntPtr FindWindow(String sClassName, String sAppName);

		[DllImport("user32.dll", CharSet = CharSet.Unicode)]
		static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, String lpszClass, String lpszWindow);

		public static bool Update()
		{
			//Console.WriteLine("TouchscreenMode.Update(): _osk_visible={0}, OnscreenKeyboardVisible={1}", _osk_visible, OnscreenKeyboardVisible);
			
			if (_osk_visible == OnscreenKeyboardVisible)
				return true;

			if (OnscreenKeyboardVisible == false)
			{
				TouchscreenMode.ToggleOnscreenKeyboard(false);
				_osk_visible = false;
			}
			else
			{
				TouchscreenMode.ToggleOnscreenKeyboard(true);
				_osk_visible = true;
			}

			return true;
		}

		public static void ToggleOnscreenKeyboard(bool show)
		{
			try
			{
				if (show == true && TouchscreenMode.FinderWindow.WindowHeight < TouchscreenMode.DefaultWindowHeight)
					return;

				if (show == false && TouchscreenMode.FinderWindow.WindowHeight == TouchscreenMode.DefaultWindowHeight)
					return;

				if (show == true)
					TouchscreenMode.FinderWindow.GtkWindow.Unmaximize();

				IntPtr parent = FindWindow("Shell_TrayWnd", null);
				Console.WriteLine("parent: " + parent);
				IntPtr child1 = FindWindowEx(parent, IntPtr.Zero, "TrayNotifyWnd", "");
				Console.WriteLine("child1: " + child1);
				IntPtr keyboardWnd = FindWindowEx(child1, IntPtr.Zero, null, "Bildschirmtastatur");
				Console.WriteLine("keyboardWnd: " + keyboardWnd);

				uint WM_LBUTTONDOWN = 0x0201;
				uint WM_LBUTTONUP = 0x0202;
				UIntPtr x = new UIntPtr(0x01);
				UIntPtr x1 = new UIntPtr(0);
				IntPtr y = new IntPtr(0x0240012);
				PostMessage(keyboardWnd, WM_LBUTTONDOWN, x, y);
				PostMessage(keyboardWnd, WM_LBUTTONUP, x1, y);

				if (show == false)
				{
					TouchscreenMode.FinderWindow.GtkWindow.Maximize();
					TouchscreenMode.scroll_state = ScrollState.Undefined;
				}
			}
			catch {}
		}

		public static void HideOnScreenKeyboard()
		{
			try
			{
				uint WM_SYSCOMMAND = 0x0112;
				UIntPtr SC_CLOSE = new UIntPtr(0xF060);
				IntPtr y = new IntPtr(0);
				IntPtr KeyboardWnd = FindWindow("IPTip_Main_Window", null);
				PostMessage(KeyboardWnd, WM_SYSCOMMAND, SC_CLOSE, y);
				TouchscreenMode.OnscreenKeyboardVisible = false;
				TouchscreenMode._osk_visible = false;
			}
			catch { }
		}

		[GLib.ConnectBefore]
		public static void OnButtonPressedLower(object o, ButtonPressEventArgs args)
		{
			if (args.Event.Button == 1)
			{
				if (TouchscreenMode.scroll_state != ScrollState.Top)
				{
					TouchscreenMode.ScrolledWindow.Vadjustment.Value = TouchscreenMode.ScrolledWindow.Vadjustment.Lower;
					TouchscreenMode.ScrolledWindow.Vadjustment.ChangeValue();
					TouchscreenMode.scroll_state = ScrollState.Top;
				}
				Entry e = o as Entry;
				e.GrabFocus();
				TouchscreenMode.OnscreenKeyboardVisible = true;
			}

			args.RetVal = false;
		}

		[GLib.ConnectBefore]
		private static void OnButtonPressedUpper(object o, ButtonPressEventArgs args)
		{
			if (args.Event.Button == 1)
			{
				if (TouchscreenMode.scroll_state != ScrollState.Bottom)
				{
					TouchscreenMode.ScrolledWindow.Vadjustment.Value = TouchscreenMode.ScrolledWindow.Vadjustment.Upper;
					TouchscreenMode.ScrolledWindow.Vadjustment.ChangeValue();
					TouchscreenMode.scroll_state = ScrollState.Bottom;
				}
				Entry e = o as Entry;
				e.GrabFocus();
				TouchscreenMode.OnscreenKeyboardVisible = true;
			}

			args.RetVal = false;
		}

		[GLib.ConnectBefore]
		private static void OnKeyPressed(object o, KeyPressEventArgs args)
		{
			if (args.Event.Key == Gdk.Key.Return || args.Event.Key == Gdk.Key.KP_Enter)
				TouchscreenMode.OnscreenKeyboardVisible = false;

			args.RetVal = false;
		}

		private static void OnFocusOut(object o, FocusOutEventArgs args)
		{
			TouchscreenMode.OnscreenKeyboardVisible = false;
		}

		private static void OnFocusInUpper(object o, FocusInEventArgs args)
		{
			if (TouchscreenMode.scroll_state != ScrollState.Bottom)
			{
				TouchscreenMode.ScrolledWindow.Vadjustment.Value = TouchscreenMode.ScrolledWindow.Vadjustment.Upper;
				TouchscreenMode.ScrolledWindow.Vadjustment.ChangeValue();
				TouchscreenMode.scroll_state = ScrollState.Bottom;
			}
			TouchscreenMode.OnscreenKeyboardVisible = true;
		}

		private static void OnFocusInLower(object o, FocusInEventArgs args)
		{
			if (TouchscreenMode.scroll_state != ScrollState.Top)
			{
				TouchscreenMode.ScrolledWindow.Vadjustment.Value = TouchscreenMode.ScrolledWindow.Vadjustment.Lower;
				TouchscreenMode.ScrolledWindow.Vadjustment.ChangeValue();
				TouchscreenMode.scroll_state = ScrollState.Top;
			}
			TouchscreenMode.OnscreenKeyboardVisible = true;
		}

		public static void InitTouchRCStyles()
		{
			Rc.ParseString("style \"TouchButton\"   { GtkButton::inner-border = {3,3,3,3} }\n class \"GtkButton\"   style \"TouchButton\"");
			Rc.ParseString("style \"TouchEntry\"    { GtkEntry::inner-border  = {0,0,7,7} }\n class \"GtkEntry\"    style \"TouchEntry\"");
			Rc.ParseString("style \"TouchCombo\"    { GtkComboBox::arrow-size = 27        }\n class \"GtkComboBox\" style \"TouchCombo\"");
			Rc.ParseString("style \"TouchSlider\"   { GtkRange::slider-width  = 30        }\n class \"GtkRange\"    style \"TouchSlider\"");
		}

		public static void InitEntry(Entry entry, bool top)
		{
			if (top)
				entry.ButtonPressEvent += TouchscreenMode.OnButtonPressedLower;
			else
				entry.ButtonPressEvent += TouchscreenMode.OnButtonPressedUpper;
			
			entry.KeyPressEvent += TouchscreenMode.OnKeyPressed;
			entry.FocusOutEvent += TouchscreenMode.OnFocusOut;

			if (top)
				entry.FocusInEvent += TouchscreenMode.OnFocusInLower;
			else
				entry.FocusInEvent += TouchscreenMode.OnFocusInUpper;
		}
	}


	public partial class FinderWindow
	{
		
		[Widget] Gtk.Table substance_table = null;
		[Widget] Gtk.Table info_table      = null;


		private void IntitializeTouchscreenMode()
		{
			Plugin.host.ShowInfoMessage(this.finder_window, 
			                            "Starting in Touchscreen Mode (experimental). To disable this mode, unset environment" +
			                            "variable APOIDENT_TOUCHSCREEN_MODE.");
			
			this.main_table.Remove(this.tool_design_viewport);
			this.main_table.Remove(this.design_left_viewport);
			this.main_table.Attach(this.tool_design_viewport, 0, 1, 0, 1);
			this.main_table.Attach(this.design_left_viewport, 0, 1, 1, 5);

			this.main_table.Remove(this.design_top_viewport);
			this.main_table.Remove(this.tool_viewport);
			this.main_table.Remove(this.status_viewport);
			this.main_table.Remove(this.design_bottom_viewport);
			this.main_table.Remove(this.scroll_viewport);
			this.main_table.Attach(this.scroll_viewport, 1, 2, 0, 5);
			this.status_viewport.Visible = false;
			this.status_viewport.NoShowAll = true;

			this.substance_table.RowSpacing = 0;
			this.info_table.RowSpacing = 0;

			TouchscreenMode.HideOnScreenKeyboard();

			this.finder_window.Maximize();
			Plugin.host.ProcessEvents();
			int h, w;
			this.finder_window.GetSize(out w, out h);
			this.finder_window.Unmaximize();
			this.finder_window.Hide();
			this.finder_window.DefaultWidth = w;
			this.finder_window.DefaultHeight = h;
			this.finder_window.Show();
			this.finder_window.Move(0, 0);

			TouchscreenMode.DefaultWindowHeight = h;

			this.main_scrolledwindow.VscrollbarPolicy = PolicyType.Automatic;
			this.main_scrolledwindow.SetScrollAdjustments(this.main_viewport.Hadjustment, this.main_viewport.Vadjustment);

			TouchscreenMode.ScrolledWindow = this.main_scrolledwindow;
			TouchscreenMode.FinderWindow   = this;

            TouchscreenMode.InitEntry(this.substance_search_entry, true);
			TouchscreenMode.InitEntry(this.user_regexentry.Entry, false);
			TouchscreenMode.InitEntry(this.supplier_regexentry.Entry, false);
            TouchscreenMode.InitEntry(this.batch_regexentry.Entry, false);
			TouchscreenMode.InitEntry(this.pzn_regexentry.Entry, false);
            TouchscreenMode.InitEntry(this.corr_fac_regexentry.Entry, false);
            TouchscreenMode.InitEntry(this.comment_regentry.Entry, false);

			GLib.Timeout.Add(200, TouchscreenMode.Update);
		}

		public int WindowHeight
		{
			get 
			{ 
				int h, w;
				this.finder_window.GetSize(out w, out h);
				return h;
			}
		}
	}
}