import tkinter as Tk
import tkinter.messagebox

from functools import partial

from .base import BaseNode
from .main import center_window
from .. import model

class CaseNode(BaseNode):
    '''Change the case of letters in a word
    '''

    def __init__(self, controller, master=None, **kwargs):
        BaseNode.__init__(self, controller, master=master, title='Case', **kwargs)
        self.sub_popup = None
        self.chk_subs = []
        self.sub_type = None

    def add_upper_button(self):
        mb = Tk.Menubutton(self.upper_frame, text=' + ', relief='raised', font=('Helvetica', '14'))
        mb.menu = Tk.Menu(mb, tearoff=0)
        mb['menu'] = mb.menu
        label = 'No Case Change'
        mb.menu.add_command(label=label, command=partial(self.controller.add_attr, label=label, node_view=self, attr_class=model.NothingMutatorAttr))

        m_cases = [None, None]
        for i, case in enumerate(['Lowercase', 'Uppercase']):
            m_cases[i] = Tk.Menu(mb, tearoff=0)
            mb.menu.add_cascade(label='{}'.format(case), menu=m_cases[i], underline=0)
            for type_ in ['All', 'First']:
                if type_ == 'First':
                    if case == 'Lowercase':
                        suffix = ', Upper Rest'
                    else:
                        suffix = ', Lower Rest'
                else:
                    suffix = ''
                label = '{} {}{}'.format(case, type_, suffix)
                m_cases[i].add_command(label=label, command=partial(self.controller.add_attr, label=label, node_view=self, attr_class=model.CaseAttr, type_=type_, case=case))
        mb.menu.add_command(label='Toggle Nth...', command=partial(self.open_case_popup, 'Toggle'))

        mb.pack(side='left', fill='x', padx=10, pady=5)

    def open_case_popup(self, case):
        '''Open popup for defining the Nth character to toggle
        '''
        self.case_popup = Tk.Toplevel()
        self.case_popup.transient(self.main.master)
        self.case_popup.withdraw()
        self.case_popup.title('{}: Nth Character'.format(case))
        self.case_popup.resizable(width=False, height=False)
        self.case_popup.grab_set()
        frame = Tk.Frame(self.case_popup)
        lb = Tk.Label(frame, text='Select Number of Nth Character'.format(self.title))
        lb.pack(fill='both', side='top')

        sp_box = Tk.Frame(frame)
        lb1 = Tk.Label(sp_box, text='Number: ')
        lb1.pack(side='left', padx=5)
        self.sp_case = Tk.Spinbox(sp_box, width=12, from_=1, to=10000)
        self.sp_case.pack(side='left')
        sp_box.pack(fill='both', side='top', padx=30, pady=20)

        # Ok and Cancel buttons
        btn_box = Tk.Frame(frame)
        btn_cancel = Tk.Button(btn_box, text='Cancel', command=self.cancel_case_popup)
        btn_cancel.pack(side='right', padx=10, pady=20)
        btn_ok = Tk.Button(btn_box, text='Ok', command=partial(self.on_ok_case_popup, case), default='active')
        btn_ok.pack(side='left', padx=10, pady=20)
        btn_box.pack()
        frame.pack(fill='both', padx=10, pady=10)
        
        center_window(self.case_popup, self.main.master)
        self.case_popup.bind('<Return>', lambda e: self.on_ok_case_popup(case))
        btn_ok.focus_set()

    def cancel_case_popup(self, *args):
        if self.case_popup:
            self.case_popup.destroy()
            self.case_popup = None

    def on_ok_case_popup(self, case, *args):
        '''OK in Custom Number Window was selected, create the attribute.
        case: 'Uppercase' or 'Lowercase'
        '''
        try:
            val_case = int(self.sp_case.get())
        except ValueError:
            tkinter.messagebox.showerror('Invalid Value', 'Invalid Value: N must be an integer', parent=self.main)
            return

        if val_case < 1:
            tkinter.messagebox.showerror('Invalid Value', 'Invalid Value: N must be greater than 0', parent=self.main)
            return
        
        ordinal = '%d%s' % (val_case, 'tsnrhtdd'[(val_case / 10 % 10 != 1) * (val_case % 10 < 4) * val_case % 10::4])
        label = '{}: {}'.format(case, ordinal)
        self.controller.add_attr(label=label, node_view=self, attr_class=model.CaseAttr, type_='Toggle', case=case, idx=val_case-1)
        self.cancel_case_popup()
