import sys
from os.path import split

path = split(split(sys.argv[0])[0])[0]
if path not in sys.path:
    sys.path.append(path)

from wxs import Ctrl, route, url_for, request, redirect
from wxs import wx as wx
from functools import wraps

rows = [('A','B','C','D','E'),
        ('STO','(',')','<=','CE'),
        ('7','8','9','-','%',),
        ('4','5','6','+','^'),
        ('1','2','3','x','INV' ),
        ('0','.','Round','/','=')]

tooltips = {'STO': 'Stores the result\ninto a variable',
            'CE': 'Clear the current\ncalculated result',
            '<=': 'Delete the last character',
            '%': 'Division module calculation',
            '^': 'Math potentiation',
            'INV': 'Inverts a result\n 1/x',
            'Round': 'Rounds a result by a\nnumber of significative cifres',
            '/': 'Division',
            '.': 'Floating point' ,
            'x': 'Multiply',
            '+': 'Add',
            '-': 'Substract',
            '=': 'Evalutates the expresion'}

variables = {'A':0,
             'B':0,
             'C':0,
             'D':0,
             'E':0,}

@route('error_message')
def showerror(main):
    # se desactiva todos los botones
   for btnrow in rows:
        for btnName in btnrow:
            if btnName == 'CE':
                continue
            main[btnName].Enable(False)

@route('clearscreen')
def clearscr(main):
    main['resultado'] = ''
    for btnrow in rows:
        for btnName in btnrow:
            if btnName == 'CE':
                continue
            main[btnName].Enable(True)

@route('Enter_pressed')
def enter_pressed(main):
    main['resultado'] = str( eval( str(main['resultado'])))

@route('Round_pressed')
def Round_pressd(main):
    if main['Round']:
        for btnrow in rows:
            for btnName in btnrow:
                if btnName in ('', 'Round') \
                    or btnName in [str(i) for i in range(10)]:
                    continue
                main[btnName].Enable(False)
    else:
        for btnrow in rows:
            for btnName in btnrow:
                if btnName in ('', 'Round') \
                    or btnName in [str(i) for i in range(10)]:
                    continue
                main[btnName].Enable(True)

@route('STO_pressed')
def STO_pressd(main):
    if main['STO']:
        # if is pressed
        # se desactivan todos los botones
        for btnrow in rows:
            for btnName in btnrow:
                if btnName in ('', 'STO') \
                    or btnName in rows[0]:
                    continue
                main[btnName].Enable(False)
    else:
        for btnrow in rows:
            for btnName in btnrow:
                if btnName in ('', 'STO') \
                    or btnName in rows[0]:
                    continue
                main[btnName].Enable(True)

@route('btn_pressed')
def keyboard_pressed(main):
    keycode = request.GetUnicodeKey()
    if keycode == 13:
        # se evalua
        return redirect('update', main=main, pressed='=')
    elif keycode == 27:
        return redirect('clearscreen', main=main)
    request.Skip()

@route('update')
def listener(main, pressed):
    def enter():
        main['resultado'] = str( eval( str(main['resultado'])))
    if pressed == '=':
        enter()
    elif pressed == 'CE':
        return redirect('clearscreen', main=main)
    elif pressed == '<=':
        if len(main['resultado']) > 0:
            main['resultado'] = str(main['resultado'])[:-1]
    elif pressed == 'x':
        if len(main['resultado']) > 0:
            main['resultado'] += '*'
    elif pressed in ('A','B','C','D','E','F'):
        if main['STO']:
            try:
                variables[pressed] = eval(str(main['resultado']))
            finally:
                main['STO'] = not main['STO'] 
                return redirect('STO_pressed', main=main)
        else:
            main['resultado'] += str(variables[pressed])
    elif pressed in (str(i) for i in range(10)) and main['Round']:
        enter()
        try:
            main['resultado'] = str(round(float(main['resultado']), int(pressed)))
        finally:
            main['Round'] = not main['Round']
            return redirect('Round_pressed', main=main)
    elif pressed == '^':
        main['resultado'].AppendText('**')
    elif pressed == 'INV':
        enter()
        if float(main['resultado']) == 0:
            main['resultado'] = 'Zero Division Error'
            return redirect('error_message',  main=main)
        main['resultado'] = str(1/float(main['resultado']))
    else:
        main['resultado'].AppendText(pressed)

def Calculator():
    buttom = Ctrl.Sizer([
        Ctrl.Sizer([Ctrl.Button(i, name=i, pointsize=13, size=wx.Size(55, 45)) \
                    if (i not in ("STO", 'Round')) \
                    else Ctrl.ToggleButton(i, name=i, pointsize=13, size=wx.Size(55, 45)) \
                    for i in j2 \
                     ],
                   flag=None)\
                         for j2 in rows],
        title='-',
        horz=wx.VERTICAL,
        horzCenter=True)
    main = Ctrl.Sizer([Ctrl.Text('', name='resultado',
                                 proportion=1,
                                 pointsize=18,
                                 size=wx.Size(295,50),
                                 style=wx.TE_PROCESS_ENTER ),
                       buttom],
                       border=0,
                       horz=wx.VERTICAL,
                       title= '-', 
                       horzCenter=True,
                       flag=None)
    for listbuttons in rows:
        for btn in listbuttons:
            if btn in ('',' '):
                continue
            elif btn in ('STO', 'Round'):
                main[btn].Bind(wx.EVT_TOGGLEBUTTON, url_for(btn+'_pressed', main=main))
            main[btn].Bind(wx.EVT_BUTTON, url_for('update', main=main,  pressed=main[btn].name))
            if (btn in tooltips) and (btn in main):
                main[btn].tooltip = tooltips[btn]
    main['resultado'].Bind(wx.EVT_KEY_DOWN, url_for('btn_pressed', main=main))
    return main

if __name__ == '__main__':
    app = wx.App()
    mainFrame = Calculator()
    mainFrame.asFrame(title='wxs demo', size=wx.Size(340,460)).Show()
    app.MainLoop()