
import sys
import errors
import window

def choose_from (win, prompt, choices):

    """ choices should be an array of pairs.  The first item in
    each pair should be a string for the user to select.  The second
    item should be a value to return. """

    # I apologize for the scrolling code... I kind of hacked it in
    # there...

        
    # Determine size of needed window
    rows = len (choices) + 2      # include space for border/prompt
    cols = 0
    for c in choices:
        l = len (c[0])
        if l > cols: cols = l
        pass
    if len (prompt) > cols: cols = len (prompt)
    cols += 4 # space for border

    scrwidth = win.width - 7
    scrheight = win.height - 4

    # too tall for screen?
    maxtopidx = rows - scrheight
    if maxtopidx > 0:
        rows = scrheight
        pass

    # too wide for screen?
    maxcol = cols - scrwidth
    if maxcol > 0:
        cols = scrwidth
        pass
    
    # Center on screen
    y = win.height/2 - rows/2
    x = win.width/2 - cols/2
    subwin = win.newwin (rows+2, cols+2, y, x)
    curcol = 0 # for horizontal scrolling of entries that are too long
    curtoprow = 0
    dispchoices = rows-2

    def _output_choice (idx, attr):
        y = 3+idx - curtoprow
        cstr = win.str (choices[idx][0])
        if len (cstr) > cols-1:
            cstr = cstr[curcol:curcol+cols-2]
            pass
        while len (cstr) < cols-1:
            cstr += " "
            pass
        win.debug ("Outputting Choice at idx=%d,y=%d,cstr='%s'\n",
                   idx, y, cstr)
        subwin.addstr (y, 2, cstr, attr)
        pass

    subwin.border ()
    subwin.addstr (1,2,prompt)
    win.debug ("Initial display of choices\n")
    for idx in range (dispchoices):
        _output_choice (idx, window.A_NORMAL)
        pass

    selidx = 0
    while 1:
        _output_choice (selidx, window.A_BOLD)
        subwin.refresh ()
        win.untouchwin ()
        ch = win.getch ()
        _output_choice (selidx, window.A_NORMAL)

        redispall = 0
        subwin.debug ('ch=%d\n' % ch)
        if ch == window.KEY_UP:
            selidx -= 1
            if selidx < 0: selidx = len (choices) - 1
            pass
        elif ch == window.KEY_DOWN:
            selidx += 1
            if selidx >= len (choices): selidx = 0
            pass
        elif ch == window.KEY_NPAGE:
            selidx += dispchoices
            # do not wrap on page down:
            if selidx >= len (choices): selidx = len(choices)-1
            pass
        elif ch == window.KEY_PPAGE:
            selidx -= dispchoices
            # do not wrap on page up:
            if selidx < 0: selidx = 0
            pass
        elif ch == window.KEY_LEFT:
            redispall = 1
            curcol -= 1
            if curcol < 0: curcol = 0
            pass
        elif ch == window.KEY_RIGHT:
            redispall = 1
            curcol += 1
            if curcol > maxcol: curcol = maxcol 
            pass
        elif ch == 10 or ch == 13: # ENTER!
            return choices[selidx][1]

        oldtoprow = curtoprow
        curtoprow = selidx - dispchoices + 1
        if curtoprow < 0:
            curtoprow = 0
            pass

        if oldtoprow != curtoprow or redispall:
            win.debug ("Refresh b/c oldtoprow=%s curtoprow=%s redispall=%s\n",
                       oldtoprow, curtoprow, redispall)
            for idx in range (dispchoices):
                win.debug ("line %d/%d contains idx %d (selidx=%d)\n",
                           idx, dispchoices, curtoprow+idx, selidx)
                _output_choice (curtoprow+idx, window.A_NORMAL)
                pass
            pass

        pass

    assert False
    pass

def test (win):
    win.debug_on ()
    _test (win, 1)
    _test (win, 0)
    pass

def _test (win, wackos):
    global choiceres
    choices = [ ('Niko', 'you picked niko'),
                ('Emily','you picked emily'),
                ('Third Choice', None) ]

    if wackos:
        choices.append (('A reaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaallly long choice!', 'you picked long!'))
        for idx in range (50):
            choices.append ( ('Choice#%d' % idx, 'you picked %d' % idx) )
            pass
        pass
    
    choiceres = choose_from (win, 'Pick One Bozo', choices)
    pass
        
if __name__ == "__main__":
    window.start (test)
    pass
    
