"""
Curses List Picker
"""
from os import environ
from sys import maxsize
from .action import Action
from .keys import get_keys

environ.setdefault("ESCDELAY", "12")  # otherwise it takes an age!


class Event(Action):
    """
    Instantiate mapping of keys to actions, which is used by modules'
    main getter method that instigates the main event loop.
    """

    def __init__(
        self,
        stdscr,
        items,
        limit=maxsize,
        numbers=False,
        header="PICK ITEMS FROM THIS LIST:",
        footer="Press [?] to view keybindings",
    ):
        Action.__init__(self, stdscr, items)
        self.limit, self.numbers = limit, numbers
        self.header, self.footer = header, footer
        self.desc, self.keys = get_keys()

        self.pad_actions = {
            **dict.fromkeys(self.keys["resize"], self.resize),
            **dict.fromkeys(self.keys["down"], self.down_pad),
            **dict.fromkeys(self.keys["up"], self.up_pad),
            **dict.fromkeys(self.keys["pgdn"], self.pgdn_pad),
            **dict.fromkeys(self.keys["pgup"], self.pgup_pad),
            **dict.fromkeys(self.keys["top"], self.top_pad),
            **dict.fromkeys(self.keys["bottom"], self.bottom_pad),
            **dict.fromkeys(self.keys["quit"], self.quit),
        }

        self.row_actions = {  # https://stackoverflow.com/a/45928598
            **dict.fromkeys(self.keys["resize"], self.resize),
            **dict.fromkeys(self.keys["right"], self.right_col),
            **dict.fromkeys(self.keys["left"], self.left_col),
            **dict.fromkeys(self.keys["down"], self.down_row),
            **dict.fromkeys(self.keys["up"], self.up_row),
            **dict.fromkeys(self.keys["top"], self.first_item),
            **dict.fromkeys(self.keys["bottom"], self.last_item),
            **dict.fromkeys(self.keys["pgdn"], self.pgdn_row),
            **dict.fromkeys(self.keys["pgup"], self.pgup_row),
            **dict.fromkeys(self.keys["goto"], self.goto),
            **dict.fromkeys(
                self.keys["find"], lambda: self.match("Find: ", self.matches, self.pick)
            ),
            **dict.fromkeys(
                self.keys["next_find"], lambda: self.goto_next(self.matches)
            ),
            **dict.fromkeys(
                self.keys["prev_find"], lambda: self.goto_prev(self.matches)
            ),
            **dict.fromkeys(
                self.keys["next_pick"], lambda: self.goto_next(self.picked)
            ),
            **dict.fromkeys(
                self.keys["prev_pick"], lambda: self.goto_prev(self.picked)
            ),
            **dict.fromkeys(self.keys["reset"], self.reset),
            **dict.fromkeys(self.keys["recenter"], self.recenter_row),
            **dict.fromkeys(
                self.keys["pick"],
                lambda: self.pick(self.currow, self.picked) or self.down_row(),
            ),
            **dict.fromkeys(
                self.keys["pick_pattern"],
                lambda: self.match("Pick: ", self.picked, self.pick),
            ),
            **dict.fromkeys(self.keys["undo"], self.undo),
            **dict.fromkeys(self.keys["undo_up"], self.undo_up),
            **dict.fromkeys(
                self.keys["toggle"], lambda: self.toggle(self.currow, self.picked)
            ),
            **dict.fromkeys(
                self.keys["toggle_down"],
                lambda: self.toggle(self.currow, self.picked) or self.down_row(),
            ),
            **dict.fromkeys(
                self.keys["toggle_up"],
                lambda: self.toggle(self.currow, self.picked) or self.up_row(),
            ),
            **dict.fromkeys(self.keys["toggle_all"], self.toggle_all),
            **dict.fromkeys(
                self.keys["toggle_pattern"],
                lambda: self.match("Toggle: ", self.picked, self.toggle),
            ),
            **dict.fromkeys(
                self.keys["view_picks"],
                lambda: self.view(contents=[self.items[pick] for pick in self.picked]),
            ),
            **dict.fromkeys(self.keys["view_help"], lambda: self.view(self.desc)),
            **dict.fromkeys(self.keys["save"], self.save),
            **dict.fromkeys(self.keys["quit"], self.quit),
        }

    def view(self, contents):
        if not contents:
            contents = ["", "Nothing to see here..."]

        # save state before reinitialising the body... this is very ugly...
        items, pminrow = self.items, self.pminrow
        currow, curcol = self.currow, self.curcol
        self.items, self.pminrow = contents, 0

        self.body_init()
        self.refresh()

        while True:
            self.draw_body(contents, numbers=False, pick=False)
            self.draw_header("Press [UP] [DOWN] [PGUP] [PGDN] to scroll.")
            self.draw_footer("Press [q] or [ESC] to return to picker.")
            self.refresh()
            key = self.stdscr.getch()
            try:
                if self.pad_actions[key]() == "quit":
                    break
            except KeyError:
                pass

        # restore the content state
        self.items = items
        self.body_init()
        # restore our previous position in the page... yes this is naff!
        self.pminrow, self.currow, self.curcol = pminrow, currow, curcol
        self.refresh()

    def get_picks(self):
        """
        Main event loop that draws the screen, waits for input, and executes an
        action based on that input. If the method executed returns true, we
        return our objects' picked attribute.
        """
        header, footer, out = self.header, self.footer, None
        while True:
            self.draw_body(self.items, numbers=self.numbers)
            self.draw_header(header)
            self.draw_footer(footer)
            self.refresh()
            key = self.stdscr.getch()
            try:
                out = self.row_actions[key]()
                if out == "quit":
                    return [self.items[pick] for pick in self.picked]
            except KeyError:
                pass
            if len(self.picked) > self.limit:
                if self.limit == 1:
                    del self.picked[: self.limit]
                else:
                    del self.picked[self.limit :]
                header, footer = ("MAXIMUM PICK LIMIT REACHED!",) * 2
            elif out:
                footer = out
            else:
                header, footer = self.header, self.footer
