#!/usr/bin/env python

# This file is part of Window-Switch.
# Copyright (c) 2009-2013 Antoine Martin <antoine@nagafix.co.uk>
# Window-Switch is released under the terms of the GNU GPL v3

#@PydevCodeAnalysisIgnore

import os

from winswitch.util.simple_logger import Logger

import win32con
import win32gui
import win32process
import win32pdh
import win32ui
import win32api

from ctypes import CFUNCTYPE, c_long, c_int, c_uint, c_ulong


# http://code.activestate.com/recipes/208699/
# window_hook(self, nCode, wParam, lParam)
WIN_HOOK = CFUNCTYPE(c_long, c_int, c_uint, c_long)
# http://www.cs.unc.edu/Research/assist/doc/pyhook/public/pyHook.HookManager.HookConstants-class.html
WH_CALLWNDPROCRET = 4


class win32_wm:
	def	__init__(self):
		Logger(self, log_colour=Logger.HIGHLIGHTED_BROWN)
		self.our_hwnd = []
		self.shell_tray_window = None
		self.dll_handle = None
		self.hook_handle = None
		self.call_next_hook = None
		self.raise_windows = None
		if False:
			self.hook_notifications()

	def close(self):
		#FIXME: unregister hook..
		pass

	def hook_notifications(self):
		self.debug()
		try:
			import ctypes
			self.sdebug("user32=%s" % ctypes.windll.user32)
			self.dll_handle = ctypes.windll.user32._handle
			self.sdebug("user32.handle=%s" % self.dll_handle)
			#self.debug("() user32=%s" % ctypes.windll.sysmsg)
			self.sdebug("SetWindowsHookExA=%s" % ctypes.windll.user32.SetWindowsHookExA)
			self.call_next_hook = ctypes.windll.user32.CallNextHookEx
			self.sdebug("CallNextHookEx=%s" % self.call_next_hook)

			#WH_CALLWNDPROCRET = 12
			self.hook_handle = ctypes.windll.user32.SetWindowsHookExA(WH_CALLWNDPROCRET, WIN_HOOK(self.window_hook), self.dll_handle, 0)
			# This does not work as we need to register a function in a DLL if dwThreadId=0 :
			#http://msdn.microsoft.com/en-us/library/ms644990(VS.85).aspx
			self.sdebug("hook_handle=%s" % self.hook_handle)
			if self.hook_handle == 0:
				error = win32api.GetLastError()
				self.serror("error=%s" % error)
		except Exception, e:
			self.exc(e)

	def window_hook(self, nCode, wParam, lParam):
		self.sdebug(None, nCode, wParam, lParam)
		v = self.call_next_hook(self.hook_handle, nCode, wParam, lParam)
		self.sdebug("next hook returned %s" % v, nCode, wParam, lParam)
		return	v

	def get_our_windows(self):
		return	self.our_hwnd

	def get_shell_tray_window(self):
		tray_window = win32gui.FindWindow("Shell_TrayWnd", None)
		if not tray_window:
			return	None
		tray_notify_window = win32gui.FindWindowEx(tray_window, 0, "TrayNotifyWnd", None)
		return	tray_notify_window


	def close_callback(self, window, pid):
		self.sdebug(Nome, window, pid)
		win32gui.PostMessage( window, win32con.WM_CLOSE,0,0)

	def close_windows(self, pids):
		self.for_matching_pids(pids, self.close_callback)

	def minimize_callback(self, window, pid):
		self.sdebug(None, window, pid)
		win32gui.FlashWindowEx( window, 0, 2, 200)
		win32gui.ShowWindow(window, win32con.SW_MINIMIZE)

	def minimize_windows(self, pids):
		self.for_matching_pids(pids, self.minimize_callback)

	def for_matching_pids(self, pids, callback):
		self.sdebug(None, pids, callback)
		try:
			desktop = win32gui.GetDesktopWindow()
			window = win32gui.GetWindow(desktop, win32con.GW_CHILD)
			while window:
				title = win32gui.GetWindowText(window)
				window_pids = win32process.GetWindowThreadProcessId(window)
				for window_pid in window_pids:
					if window_pid in pids:
						self.sdebug("found matching window '%s'" % window_pid, pids, callback)
						callback(window, window_pid)
				previous = window
				window = win32gui.GetWindow(previous, win32con.GW_HWNDNEXT)
		except Exception, e:
			self.serr(None, e, pids,callback)

	def is_screensaver_running(self):
		return	win32gui.SystemParametersInfo(win32con.SPI_GETSCREENSAVERRUNNING, None, 0)

	def get_modifiers_set(self):
		modifiers = []
		from winswitch.consts import MODIFIER_KEY_SHIFT, MODIFIER_KEY_CONTROL, MODIFIER_KEY_ALT
		if (win32api.GetKeyState(win32con.VK_SHIFT) & 0x8000)!=0:
			modifiers.append(MODIFIER_KEY_SHIFT)
		if (win32api.GetKeyState(win32con.VK_CONTROL) & 0x8000)!=0:
			modifiers.append(MODIFIER_KEY_CONTROL)
		if (win32api.GetKeyState(win32con.VK_MENU) & 0x8000)!=0:
			modifiers.append(MODIFIER_KEY_ALT)
		return	modifiers
