::requires 'ooSQLite.cls'
::requires "rxunixsys" LIBRARY
::requires 'ncurses.cls'
::requires 'app/utils.rex'

::class AddressBookUI public

    ::method init
      expose win mainMenu
      return

    ::method initialize
      expose win mainMenu

      win = self~DrawMainPanel(0, .true) /* default colour, draw border box */
      self~setupMainMenu(win)
      return

    ::METHOD DrawMainPanel
        use arg clrset, with_box
        win = .window~new()                    /* The first invocation must be with no arguments */
        win~curs_set(0)                        /* Hide the cursor by default                     */
        win~keypad(1)                          /* Enable function keys and arrow keys            */
        win~raw
        win~noecho
        win~clear
        win~cbreak

        self~SetPanelColor(win, clrset)

        if with_box = .true then DO
            win~box(0, 0) /* Draw box with default ACS characters */
            win~refresh
        END
    return win

    ::METHOD DrawSubPanel
        use arg height, width, starty, startx, clrset, title, with_box
        new_win = .window~new(height, width, starty, startx)
        new_win~curs_set(0)

        /* Set the panel color */
        self~SetPanelColor(new_win, clrset)

        /* Display title */
        new_win~attron(new_win~A_BOLD)
        new_win~mvaddstr(starty-(starty-2), (width - title~length) % 2, title)
        new_win~attroff(new_win~A_BOLD)
        new_win~refresh
        if with_box = .true then DO
            new_win~box(0,0)
            new_win~refresh
        END
    return new_win

    ::METHOD SetPanelColor
        use arg panel, clrset

        panel~start_color()
        SELECT
            /* white text on blue background */
            when clrset = 1 then panel~init_pair(2, panel~COLOR_WHITE, panel~COLOR_BLUE)
            /* white text on grey background */
            when clrset = 2 then panel~init_pair(3, panel~COLOR_WHITE, panel~COLOR_GREEN)
            /* yellow text on red background */
            when clrset = 3 then panel~init_pair(4, panel~COLOR_YELLOW, panel~COLOR_RED)
            /* black text on white background */
            when clrset = 4 then panel~init_pair(5, panel~COLOR_BLACK, panel~COLOR_WHITE)
            /* black text on green background */
            when clrset = 5 then panel~init_pair(6, panel~COLOR_BLACK, panel~COLOR_GREEN)
            /* black text on cyan background */
            when clrset = 6 then panel~init_pair(7, panel~COLOR_BLACK, panel~COLOR_CYAN)
            /* Default to white text on black background */
            OTHERWISE DO
                clrset=0
                panel~init_pair(1, panel~COLOR_WHITE, panel~COLOR_BLACK)
            END
        END
        panel~bkgd(panel~color_pair(clrset+1))
        panel~refresh
    RETURN

    ::method setupMainMenu
        expose mainMenu menuwin menu_items menu_keys selected
        use arg win

        max_y = win~lines
        max_x = win~cols

        menu_height = 21
        menu_width = 40
        start_y = (max_y - menu_height) % 2
        start_x = (max_x - menu_width) % 2
        clrset=1
        title = "Rexx Address Book"
        with_box = .true

        menuwin = self~DrawSubPanel(menu_height, menu_width, start_y, start_x, clrset, title, with_box)
        menu_items = .array~of("[A]dd Contact", "[R]emove Contact", "[E]dit Contact", "[S]earch", "[L]ist All", "[Q]uit")
        menu_keys = .array~of("a", "r", "e", "s", "l", "q")

        /* Display menu items */
        .environment~selected = 1
        self~DrawMenu(menuwin, menu_items, .environment~selected, win)
        menuwin~refresh
    RETURN

    ::method DrawMenu
      expose win menu_items menu_keys selected mainwin
      use arg menuwin, items, selected, mainwin

      do i = 1 to items~items
        if i = .environment~selected then do
          menuwin~attron(menuwin~attron(menuwin~A_REVERSE))
          menuwin~attron(menuwin~A_BOLD)
          menuwin~mvaddstr(i+3, 2, items[i])
          menuwin~attroff(menuwin~A_REVERSE)
          menuwin~attroff(menuwin~A_BOLD)
        end
        else do
          menuwin~mvaddstr(i+3, 2, items[i])
        end
      end
      menuwin~refresh
      return

    /** MAIN LOOP **/
    ::method mainLoop
      expose win mainMenu menuwin selected menu_items menu_keys
      menuwin~refresh
      running = .true

      do while running
        key = win~getch

        old_selected = .environment~selected

        select
          when key = menuwin~KEY_UP then do
            if .environment~selected > 1 then .environment~selected = .environment~selected - 1
            self~DrawMenu(menuwin, menu_items, .environment~selected, win)
            menuwin~refresh
          end
          when key = menuwin~KEY_DOWN then do
            if .environment~selected < menu_items~items then .environment~selected = .environment~selected + 1
            self~DrawMenu(menuwin, menu_items, .environment~selected, win)
            menuwin~refresh
          end
          when key = D2C(81) | key = D2C(113) | key = "q" | key = C2D("q") then do
            menuwin~endwin
            .environment['STOPNOW'] = 1
            RETURN
          end
          when key = D2C(10) | key = D2C(13) then do /* Enter key - numeric codes only */
            menuwin~mvaddstr(19 - 1, 18, "Letter selection ["||menu_keys[.environment~selected]||"]")
            menuwin~refresh
            call SysWait 0.25
            self~ProcessSelection(menuwin, menu_keys[.environment~selected])
            return
          end
          otherwise do
            if datatype(key) = 'CHAR' then do
              key = lower(key)
              pos = self~findInArray(menu_keys, key)
              if pos > 0 then do
                menuwin~mvaddstr(19 - 1, 18, "Letter selection ["||key||"]")
                menuwin~refresh
                call SysWait 0.25
                self~ProcessSelection(menuwin, key)
                return
              end
            end
          end /* otherwise */
        end /* select */
        /* Only redraw if selection changed */
        if old_selected \= .environment~selected then do
            self~DrawMenu(menuwin, menu_items, .environment~selected, win)
        end
      end /* do while running */
    return

    /* Process selection */
    ::METHOD  ProcessSelection
        expose menu_items menu_keys
        use arg menuwin, key_char
          select
            when key_char = 'a' then do
                menuwin~mvaddstr(19 - 3, 5, "I would launch the ADD panel     ");
                menuwin~refresh
                call SysWait 0.25
                END
            when key_char = 'r' then do
                menuwin~mvaddstr(19 - 3, 5, "I would launch the REMOVE panel  ");
                menuwin~refresh
                call SysWait 0.25
                END
            when key_char = 'e' then do
                menuwin~mvaddstr(19 - 3, 5, "I would launch the EDIT panel    ");
                menuwin~refresh
                call SysWait 0.25
                END
            when key_char = 's' then do
                menuwin~mvaddstr(19 - 3, 5, "I would launch the SEARCH panel  ");
                menuwin~refresh
                call SysWait 0.25
                END
            when key_char = 'l' then do
                menuwin~mvaddstr(19 - 3, 5, "I would launch the LIST panel    ")
                menuwin~refresh
                call SysWait 0.25
                END
            when key_char = 'q' then do
                menuwin~mvaddstr(19 - 3, 5, "Exiting The Application...        ");
                menuwin~refresh
                call SysWait 0.25
                menuwin~endwin
                .environment['STOPNOW'] = 1
                END
            otherwise nop
          end
    return

    ::METHOD findInArray
      use arg array, item
      do i = 1 to array~items
        if array[i] = item then return i
      end
      return 0  /* Not found */

    ::method cleanup
      expose win
      /* Clean up ncurses */
      win~endwin
      return
