"""MiniAEFrame - A minimal AppleEvent Application framework.

There are two classes:
	AEServer -- a mixin class offering nice AE handling.
	MiniApplication -- a very minimal alternative to FrameWork.py,
		only suitable for the simplest of AppleEvent servers.
"""

import sys
import traceback
import MacOS
from Carbon import AE
from Carbon.AppleEvents import *
from Carbon import Evt
from Carbon.Events import *
from Carbon import Menu
from Carbon import Win
from Carbon.Windows import *
from Carbon import Qd

import aetools
import EasyDialogs

kHighLevelEvent = 23				# Not defined anywhere for Python yet?


class MiniApplication:
	
	"""A minimal FrameWork.Application-like class"""
	
	def __init__(self):
		self.quitting = 0
		# Initialize menu
		self.appleid = 1
		self.quitid = 2
		Menu.ClearMenuBar()
		self.applemenu = applemenu = Menu.NewMenu(self.appleid, "\024")
		applemenu.AppendMenu("%s;(-" % self.getaboutmenutext())
		if MacOS.runtimemodel == 'ppc':
			applemenu.AppendResMenu('DRVR')
		applemenu.InsertMenu(0)
		self.quitmenu = Menu.NewMenu(self.quitid, "File")
		self.quitmenu.AppendMenu("Quit")
		self.quitmenu.SetItemCmd(1, ord("Q"))
		self.quitmenu.InsertMenu(0)
		Menu.DrawMenuBar()
	
	def __del__(self):
		self.close()
	
	def close(self):
		pass
	
	def mainloop(self, mask = everyEvent, timeout = 60*60):
		while not self.quitting:
			self.dooneevent(mask, timeout)
	
	def _quit(self):
		self.quitting = 1
	
	def dooneevent(self, mask = everyEvent, timeout = 60*60):
			got, event = Evt.WaitNextEvent(mask, timeout)
			if got:
				self.lowlevelhandler(event)
	
	def lowlevelhandler(self, event):
		what, message, when, where, modifiers = event
		h, v = where
		if what == kHighLevelEvent:
			msg = "High Level Event: %s %s" % \
				(`code(message)`, `code(h | (v<<16))`)
			try:
				AE.AEProcessAppleEvent(event)
			except AE.Error, err:
				print 'AE error: ', err
				print 'in', msg
				traceback.print_exc()
			return
		elif what == keyDown:
			c = chr(message & charCodeMask)
			if modifiers & cmdKey:
				if c == '.':
					raise KeyboardInterrupt, "Command-period"
				if c == 'q':
					if hasattr(MacOS, 'OutputSeen'):
						MacOS.OutputSeen()
					self.quitting = 1
					return
		elif what == mouseDown:
			partcode, window = Win.FindWindow(where)
			if partcode == inMenuBar:
				result = Menu.MenuSelect(where)
				id = (result>>16) & 0xffff	# Hi word
				item = result & 0xffff		# Lo word
				if id == self.appleid:
					if item == 1:
						EasyDialogs.Message(self.getabouttext())
					elif item > 1 and hasattr(Menu, 'OpenDeskAcc'):
						name = self.applemenu.GetMenuItemText(item)
						Menu.OpenDeskAcc(name)
				elif id == self.quitid and item == 1:
					if hasattr(MacOS, 'OutputSeen'):
						MacOS.OutputSeen()
					self.quitting = 1
				Menu.HiliteMenu(0)
				return
		# Anything not handled is passed to Python/SIOUX
		if hasattr(MacOS, 'HandleEvent'):
			MacOS.HandleEvent(event)
		else:
			print "Unhandled event:", event
	
	def getabouttext(self):
		return self.__class__.__name__
	
	def getaboutmenutext(self):
		return "About %s\311" % self.__class__.__name__


class AEServer:
	
	def __init__(self):
		self.ae_handlers = {}
	
	def installaehandler(self, classe, type, callback):
		AE.AEInstallEventHandler(classe, type, self.callback_wrapper)
		self.ae_handlers[(classe, type)] = callback
	
	def close(self):
		for classe, type in self.ae_handlers.keys():
			AE.AERemoveEventHandler(classe, type)
	
	def callback_wrapper(self, _request, _reply):
		_parameters, _attributes = aetools.unpackevent(_request)
		_class = _attributes['evcl'].type
		_type = _attributes['evid'].type
		
		if self.ae_handlers.has_key((_class, _type)):
			_function = self.ae_handlers[(_class, _type)]
		elif self.ae_handlers.has_key((_class, '****')):
			_function = self.ae_handlers[(_class, '****')]
		elif self.ae_handlers.has_key(('****', '****')):
			_function = self.ae_handlers[('****', '****')]
		else:
			raise 'Cannot happen: AE callback without handler', (_class, _type)
		
		# XXXX Do key-to-name mapping here
		
		_parameters['_attributes'] = _attributes
		_parameters['_class'] = _class
		_parameters['_type'] = _type
		if _parameters.has_key('----'):
			_object = _parameters['----']
			del _parameters['----']
			# The try/except that used to be here can mask programmer errors.
			# Let the program crash, the programmer can always add a **args
			# to the formal parameter list.
			rv = apply(_function, (_object,), _parameters)
		else:
			#Same try/except comment as above
			rv = apply(_function, (), _parameters)
		
		if rv == None:
			aetools.packevent(_reply, {})
		else:
			aetools.packevent(_reply, {'----':rv})


def code(x):
	"Convert a long int to the 4-character code it really is"
	s = ''
	for i in range(4):
		x, c = divmod(x, 256)
		s = chr(c) + s
	return s

class _Test(AEServer, MiniApplication):
	"""Mini test application, handles required events"""
	
	def __init__(self):
		MiniApplication.__init__(self)
		AEServer.__init__(self)
		self.installaehandler('aevt', 'oapp', self.open_app)
		self.installaehandler('aevt', 'quit', self.quit)
		self.installaehandler('****', '****', self.other)
		self.mainloop()

	def quit(self, **args):
		self._quit()
		
	def open_app(self, **args):
		pass
		
	def other(self, _object=None, _class=None, _type=None, **args):
		print 'AppleEvent', (_class, _type), 'for', _object, 'Other args:', args
		

if __name__ == '__main__':
	_Test()
