from ptypes import Point, Rect
import config
import curses
import os

class Dialog(object):
    def __init__(self,width,height):
        self.width=width
        self.height=height
        
    def draw(self,app):
        cx=int(app.width/2)
        cy=int(app.height/2)
        y=int(cy - self.height/2)
        x=int(cx - self.width/2)
        self.rect=Rect(x,y,x+self.width,y+self.height)
        app.draw_frame(self.rect,4)
        app.fill_rect(Rect(self.rect).inflate(-1),' ',4)

class MessageBox(Dialog):
    def __init__(self,prompt):
        super(MessageBox,self).__init__(60,8)
        self.prompt=prompt
        self.actions={}

    def add_key(self,key,action):
        self.actions[key.lower()]=action
        self.actions[key.upper()]=action
        
    def process_key(self,key):
        if key in self.actions:
            return self.actions.get(key)
        return None

    def draw(self,app):
        super(MessageBox,self).draw(app)
        app.move(Point(self.rect.tl.x+4,self.rect.tl.y+4))
        app.write(self.prompt,4)
        
class FileDialog(Dialog):
    def __init__(self,action):
        super(FileDialog,self).__init__(60,20)
        self.dir=os.getcwd()
        self.browse_mode=True
        self.edit_text=''
        self.ofs=0
        self.cur=0
        self.items=[]
        self.fill_items()
        self.action=action
    
    def fill_items(self):
        l=os.listdir(self.dir)
        for i in range(0,len(l)):
            name=l[i]
            path=os.path.join(self.dir,name)
            if os.path.isdir(path):
                name=name+'/'
            l[i]=name
        l.insert(0,'../')
        self.items=l

    def draw(self,app):
        super(FileDialog,self).draw(app)
        pos=self.rect.tl+Point(1,1)
        app.move(pos)
        app.write(self.dir+'/',1)
        self.editpos=pos+(len(self.dir)+1,0)
        pos+=(2,1)
        for i in range(0,17):
            idx=i+self.ofs
            app.move(pos)
            if idx<len(self.items):
                attr=0
                if self.cur==idx:
                    attr=curses.A_REVERSE
                s=self.items[idx]
                if len(s)>50:
                    s=s[0:50]
                if len(s)<50:
                    s=s+' '*(50-len(s))
                app.write(s,4,attr)
            else:
                app.write(' '*50,4)
            pos+=(0,1)
        if not self.browse_mode:
            app.move(self.editpos)
            app.write(self.edit_text,1)
        
    def process_key(self,key):
        if self.browse_mode:
            if key==chr(9): # tab
                self.browse_mode=False
            if key=='KEY_DOWN':
                self.cur=(self.cur+1)%len(self.items)
            if key=='KEY_UP':
                self.cur=(self.cur-1)%len(self.items)
            if key=='KEY_END':
                self.cur=len(self.items)-1
            if key=='KEY_HOME':
                self.cur=0
            if key=='KEY_PPAGE':
                self.cur=(self.cur-17)%len(self.items)
            if key=='KEY_NPAGE':
                self.cur=(self.cur+17)%len(self.items)
            if key==chr(10): # Enter
                name=self.items[self.cur]
                path=os.path.abspath(os.path.join(self.dir,name))
                if name.endswith('/'):
                    self.dir=path
                    self.fill_items()
                else:
                    return lambda: self.action(path)
            if self.cur<self.ofs or self.cur>=(self.ofs+17):
                self.ofs=self.cur-8
                if self.ofs<0:
                    self.ofs=0
        else:
            if key==chr(9): # tab
                self.browse_mode=True
            if len(key)==1 and ord(key)>32 and ord(key)<128:
                self.edit_text+=key
            if key=='KEY_BACKSPACE' and len(self.edit_text)>0:
                self.edit_text=self.edit_text[0:-1]
            if key==chr(10):
                path=os.path.abspath(os.path.join(self.dir,self.edit_text))
                return lambda: self.action(path)
        return None

class FormWidget(object):
    def __init__(self,pos):
        self.text=''
        self.pos=pos
        self.tabstop=False

class FormCheckbox(FormWidget):
    def __init__(self,pos,state=False):
        super(FormCheckbox,self).__init__(pos)
        self.tabstop=True
        self.state=state
        
    def details(self):
        return self.state
        
    def draw(self,app,tl):
        app.move(self.pos+tl-Point(1,0))
        mark='X' if self.state else ' '
        app.write('[{}]'.format(mark),4)
        app.move(self.pos+tl)
        
    def process_key(self,key):
        if key==' ':
            self.state=not self.state

class FormLabel(FormWidget):
    def __init__(self,pos,text):
        super(FormLabel,self).__init__(pos)
        self.text=text
        self.color=4
        self.pad=0

    def draw(self,app,tl):
        app.move(self.pos+tl)
        app.write(self.text,self.color)
        if self.pad>len(self.text):
            app.write(' '*(self.pad-len(self.text)),self.color)
        
class FormEdit(FormLabel):
    def __init__(self,pos,text,maxlen):
        super(FormEdit,self).__init__(pos,text)
        self.tabstop=True
        self.color=1
        self.maxlen=maxlen
        self.pad=maxlen
        
    def details(self):
        return self.text
        
    def draw(self,app,tl):
        super(FormEdit,self).draw(app,tl)
        app.move(self.pos+tl+Point(len(self.text),0))

    def process_key(self,key):
        if len(key)==1 and ord(key[0])>=32 and ord(key[0])<128:
            self.text=self.text+key
        if key=='KEY_BACKSPACE' and len(self.text)>0:
            self.text=self.text[0:-1]

    
class FormDialog(Dialog):
    def __init__(self,w,h):
        super(FormDialog,self).__init__(w,h)
        self.widgets=[]
        self.named_widgets={}
        self.cur=None

    def details(self,vals):
        res={}
        for val in vals:
            res[val[0]]=val[1]
        for name in self.named_widgets:
            res[name]=self.named_widgets.get(name).details()
        return res

    def add_widget(self,name,widget):
        if isinstance(widget,FormWidget):
            self.widgets.append(widget)
            if name:
                self.named_widgets[name]=widget
            if self.cur is None and widget.tabstop:
                self.cur=len(self.widgets)-1

    def draw(self,app):
        super(FormDialog,self).draw(app)
        for i in range(0,len(self.widgets)):
            widget=self.widgets[i]
            if self.cur != i:
                widget.draw(app,self.rect.tl)
        if not self.cur is None:
            self.widgets[self.cur].draw(app,self.rect.tl)
            
    def process_key(self,key):
        if key==chr(9): # tab
            while True:
                self.cur=(self.cur+1)%len(self.widgets)
                if self.widgets[self.cur].tabstop:
                    break
        if key=='KEY_BTAB': # back-tab
            while True:
                self.cur=(self.cur-1)%len(self.widgets)
                if self.widgets[self.cur].tabstop:
                    break
        if not self.cur is None:
            self.widgets[self.cur].process_key(key)
        return None


class FindReplaceDialog(FormDialog):
    def __init__(self,find_action,replace_action):
        super(FindReplaceDialog,self).__init__(60,20)
        self.find_action=find_action
        self.replace_action=replace_action
        self.add_widget('',FormLabel(Point(2,2),'Find:'))
        self.add_widget('find',FormEdit(Point(12,2),config.get('find_text'),40))
        self.add_widget('',FormLabel(Point(2,3),'Replace:'))
        self.add_widget('replace',FormEdit(Point(12,3),config.get('find_replace'),40))
        self.add_widget('case',FormCheckbox(Point(4,5),config.getbool('find_case')))
        self.add_widget('',FormLabel(Point(8,5),'Case Sensitive'))
        self.add_widget('regex',FormCheckbox(Point(4,6),config.getbool('find_regex')))
        self.add_widget('',FormLabel(Point(8,6),'Regular Expressions'))
        #
        self.add_widget('',FormLabel(Point(2,16),'Enter to find, Ctrl+R to replace, Ctrl+A to replace all'))
        
    def process_key(self,key):
        if key==chr(18): # Ctrl+R
            return lambda: self.replace_action(self.details([('all',False)]))
        if key==chr(1): # Ctrl+A
            return lambda: self.replace_action(self.details([('all',True)]))
        if key==chr(10): # Enter
            return lambda: self.find_action(self.details([]))
        return super(FindReplaceDialog,self).process_key(key)
        

class ColorConfigDialog(Dialog):
    def __init__(self):
        super(ColorConfigDialog,self).__init__(60,15)
        self.cur=1

    def draw(self,app):
        super(ColorConfigDialog,self).draw(app)
        pos=self.rect.tl+Point(2,2)
        for i in range(1,8):
            app.move(pos)
            attr=0
            if i==self.cur:
                attr=curses.A_REVERSE
            app.write('Color {}  '.format(i),4,attr)
            app.write('ABC',i)
            pos+=(0,1)
        pos+=Point(8,1)
        app.move(pos)
        app.write('Use left/right pgup/pgdn to change colors',4)
        app.move(pos+(0,1))
        app.write('Esc when done',4)
            
    def process_key(self,key):
        if key=='KEY_DOWN':
            self.cur=1+(self.cur%7)
        if key=='KEY_UP':
            self.cur=1+((self.cur-2)%7)

        fg=config.getint('fg{}'.format(self.cur))
        bg=config.getint('bg{}'.format(self.cur))
        if key=='KEY_LEFT':
            fg=(fg-1)%8
        if key=='KEY_RIGHT':
            fg=(fg+1)%8
        if key=='KEY_PPAGE':
            bg=(bg-1)%8
        if key=='KEY_NPAGE':
            bg=(bg+1)%8
        config.set('fg{}'.format(self.cur),fg)
        config.set('bg{}'.format(self.cur),bg)
        curses.init_pair(self.cur,fg,bg)
        return None
    