# -*- coding: utf-8 -*-
# vim: set noet ts=4:
#
# scim-python
#
# Copyright (c) 2007-2008 Yu Fan <yufanyufan@gmail.com>
#
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
# Boston, MA  02111-1307  USA
#
# $Id: $
#

from ZhengJu import *
import scim
import os
from scim import KeyCode
from scim import KeyMask
from scim import Property
import traceback
import sys
from PYDict import *
from gettext import dgettext

_ = lambda a : dgettext ("scim-python", a)
strip = lambda a: a if a == "" or a == "'" or a[0]!="'" else a[1:]
class QuanPinEngine(Engine):
	def __init__ (self, factory, config, encoding, id):
		Engine.__init__(self, factory, config, encoding, id)

	def clear(self):
		self.extra_string = ""
		Engine.clear(self)

	def get_extra_string(self):
		return self.extra_string

	def is_valid_head(self, str):
		#~ print str
		if str == "'" or strip(str)[0] in SHENGMU_LIST and (strip(str) in PINYIN_LIST or strip(str) in PINYIN_PARTIAL_LIST):
			return True
		for i in range(len(str), 0, -1):
			if strip(str)[0] in SHENGMU_LIST and strip(str[:i]) in PINYIN_LIST:
				return True
		return False

	def split(self, strs):
		if strip(strs) in PINYIN_LIST \
			or strip(strs) in PINYIN_PARTIAL_LIST	\
			or strip(strs) in SHENGMU_LIST \
			or strs == "'":
			yield (strs,  "")
		else:
			for i in range(len(strs), 0, -1):
				if strs[:i][-1] == "'":
					continue
				if strip(strs[:i]) in PINYIN_LIST:
					yield ( strs[:i], strs[i:] )
					if strip(strs[:i-1]) in PINYIN_LIST and strip(strs[:i])[-1] in SHENGMU_LIST and self.is_valid_head(strs[i-1:]):
						yield ( strs[:i-1], strs[i-1:])
					break

	def recursive_parse(self, str):
		for (word, strleft) in self.split(str):
			if strleft:
				for pinyinlist in self.recursive_parse(strleft):
					yield [word] + pinyinlist
			else:
				yield [word]
		
	def process_pinyin(self, c):
		p = u"".join( i.get_screen_pinyin() for i in self._editor.pinyinlist) + c
		all =  list(self.recursive_parse(p))
		if not all:
			raise InputException()
		min_len = 100
		freq = 0
		for q in all:
			pinyinlist = []
			for i in q:
				#~ print i,
				pinyinlist.append(PinYinWord(pinyin=i))
			#~ print len(pinyinlist)
			predicts = self._editor.get_predict_pinyinlist(pinyinlist)
			#~ print len(predicts)
			if len(predicts) < min_len:
				min_len = len(predicts)
				#~ freq = sum([i[ADJ_FREQ] for i in predicts])
				if len(predicts)>1:
					freq = self._editor.freq_alg(predicts[0],predicts[1])
				else:
					freq = predicts[0][ADJ_FREQ]
				#~ print freq
				best = (pinyinlist,predicts)
			elif len(predicts) == min_len:
					if len(predicts)>1:
						tfreq = self._editor.freq_alg(predicts[0],predicts[1])
					else:
						tfreq = predicts[0][ADJ_FREQ]
					#~ print tfreq
					if tfreq > freq:
						freq = tfreq
					best = (pinyinlist,predicts)
		self._editor.pinyinlist = best[0]
		self._editor.predict = best[1]

	def chinese_process_key_event (self, key):
		if key.mask == KeyMask.NullMask and (\
			(key.code >= KeyCode.KEY_a and key.code <= KeyCode.KEY_z) or \
			key.code == KeyCode.KEY_apostrophe):
			self.process_pinyin(unichr (key.code))
			self._editor.auto_convert_quanpin ()
			return True
		elif self._editor.pinyinlist and key.code == KeyCode.KEY_BackSpace:
			p = self._editor.pinyinlist[-1].get_screen_pinyin()
			if len(p)>1:
				self._editor.pinyinlist[-1].set_pinyin(p[:-1])
			else:
				del self._editor.pinyinlist[-1]
			self._editor.update ()
			return True
		elif (self.extra_string or self._editor.pinyinlist) and (key.code == KeyCode.KEY_Left or (key.code == KeyCode.KEY_b and key.mask & KeyMask.ControlMask)):
			if self._editor.pinyinlist:
				p = self._editor.pinyinlist[-1].get_screen_pinyin()
				self.extra_string = p + self.extra_string
				del self._editor.pinyinlist[-1]
				self._editor.update ()
			return True
		elif (self.extra_string or self._editor.pinyinlist) and (key.code == KeyCode.KEY_Right or (key.code == KeyCode.KEY_f and key.mask & KeyMask.ControlMask)):
			if self.extra_string:
				#~ print self.extra_string[0]
				self.process_pinyin( self.extra_string[0])
				self.extra_string = self.extra_string[1:]
				self._editor.auto_convert_quanpin ()
			else:
				self.extra_string = u"".join( i.get_screen_pinyin() for i in self._editor.pinyinlist)
				self._editor.pinyinlist = []
				self._editor.update()
			return True
		elif self.extra_string and key.code == KeyCode.KEY_Delete:
			if self.extra_string:
				self.extra_string = self.extra_string[1:]
				return True
			else:
				raise InputException()
		elif self.extra_string and key.code in (KeyCode.KEY_KP_Space, KeyCode.KEY_space):
			p = u"".join( i.get_screen_pinyin() for i in self._editor.pinyinlist)
			c = ""
			while True:
				c += self.extra_string[0]
				if list(self.recursive_parse(p+c)):
					self.extra_string = self.extra_string[1:]
				else:
					break				
				if not self.extra_string:
					break
			if c:
				while c:
					self.process_pinyin(c[0])
					self._editor.auto_convert_quanpin ()
					c = c[1:]
				return True
			else:
				raise InputException()
		elif Engine.chinese_process_key_event (self,key):
			return True;
		return False

class QuanPinFactory (IMEngineFactory):
	def __init__ (self, config):
		IMEngineFactory.__init__ (self, config)
		self.name 		= _(u"QuanPin")
		self.uuid 		= "00c1690f-214c-447c-be18-1db199bae183"
		self.authors	= u"Yu Fan <yufanyufan@gmail.com>"
		self.icon_file 	= "/usr/share/scim/icons/scim-python.png"
		self.credits 	= u"GPL"
		self.help		= _(u"Help For QuanPin")
		self.set_languages ("zh")
		self._config	= config
	def create_instance (self, encoding, id):
		engine =  QuanPinEngine (self, self._config, encoding, id)
		return engine

	def reload_config (self, config):
		pass
