# coding: UTF-8
"""
wx-jpBrailleKeyHook
Masataka Shinke
GPL
"""
import sys
import ctypes
from Queue import Queue
import wx


class MainFrame(wx.Frame):

    def __init__(self, parent, title, KeyGroup):
        wx.Frame.__init__(self, parent, title=title, size=(600, 400))
        font = wx.Font(32, wx.FONTFAMILY_DEFAULT,
                       wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
        self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE)
        self.control.SetFont(font)

        self.control.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
        self.control.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
        self.control.Bind(wx.EVT_CHAR, self.OnKeyChar)

        self.BrailleKeyGroup = KeyGroup
        self.q = Queue()
        self.run = True
        self.mask = 0
        for i in list(self.BrailleKeyGroup):
            self.mask += self.BrailleKeyGroup[i]
        DLLPATH = '.\\nvdaControllerClient32.dll'
        try:
            self.clientLib = ctypes.windll.LoadLibrary(DLLPATH)
            self.Pitch = None
            if self.clientLib:
                res = self.clientLib.nvdaController_testIfRunning()
                if res == 0:
                    self.Pitch = self.clientLib.nvdaController_getPitch()
                    res = self.clientLib.nvdaController_setAppSleepMode(0)

        except:
            self.clientLib = None
            self.Pitch = None

    def __del__(self):
        if self.clientLib:
            res = self.clientLib.nvdaController_testIfRunning()
            if res == 0:
                self.clientLib.nvdaController_setPitch(self.Pitch)
                res = self.clientLib.nvdaController_setAppSleepMode(0)

    def insert(self, code):
        Last = self.control.GetLastPosition()
        pos = self.control.GetInsertionPoint()
        if(Last == pos):
            self.control.AppendText(code)
        elif(pos != 0):
            buff = self.control.GetRange(pos - 1, pos) + code
            self.control.Replace(pos - 1, pos, buff)
        else:
            buff = code + self.control.GetRange(0, 1)
            self.control.Replace(0, 1, buff)
            self.control.SetInsertionPoint(0)
        if self.clientLib:
            res = self.clientLib.nvdaController_testIfRunning()
            if res == 0:
                self.clientLib.nvdaController_setPitch(self.Pitch + 50)
                self.clientLib.nvdaController_speakSpelling(code)

    def OnKeyDown(self, evt=None):
        vkCode = evt.GetKeyCode()
        d = evt
        print(vkCode)
        if (vkCode in self.BrailleKeyGroup):
            self.q.put(vkCode)
            return
        elif vkCode in range(0x21, 0x7e):
            return
        if self.clientLib:
            res = self.clientLib.nvdaController_testIfRunning()
            if res == 0:
                self.clientLib.nvdaController_setPitch(self.Pitch)
        evt.Skip()

    def OnKeyUp(self, evt=None):        
        vkCode = evt.GetKeyCode()
        if (vkCode in self.BrailleKeyGroup):
            if not self.q.empty():
                result = 0
                while(not self.q.empty()):
                    result = (result | self.BrailleKeyGroup[
                        self.q.get()]) & self.mask
                    self.q.task_done()
                self.insert(unichr(0x2800 + result))
            return
        elif vkCode in range(0x21, 0x7e):
            return
        evt.Skip()

    def OnKeyChar(self, evt=None):
        vkCode = evt.GetKeyCode()
        evt.Skip()

if __name__ == '__main__':
    app = wx.App(False)
    frame = MainFrame(
        None,
        'wx-jpBrailleKeyHook',
        KeyGroup={
            32: 0,  # " "
            83: 4,  # "S"
            68: 2,  # "D"
            70: 1,  # "F"
            74: 8,  # "J"
            75: 16,  # "K"
            76: 32,  # "L"
            # 86: 64 ,  # "V"
            # 78: 128,  # "N"
        }
    )
    frame.Show(True)
    app.MainLoop()
