# This file is part of ranger, the console file manager.
# License: GNU GPL version 3, see the file "AUTHORS" for details.

"""The base GUI element for views on the directory"""

from __future__ import (absolute_import, division, print_function)

import curses
from ranger.ext.keybinding_parser import key_to_string
from . import Widget
from ..displayable import DisplayableContainer


class ViewBase(Widget, DisplayableContainer):  # pylint: disable=too-many-instance-attributes
    draw_bookmarks = False
    need_clear = False
    draw_hints = False
    draw_info = False

    def __init__(self, win):  # pylint: disable=super-init-not-called
        DisplayableContainer.__init__(self, win)

        self.fm.signal_bind('move', self.request_clear)
        self.old_draw_borders = self.settings.draw_borders

        self.columns = None
        self.main_column = None
        self.pager = None

    def request_clear(self):
        self.need_clear = True

    def draw(self):
        if self.need_clear:
            self.win.erase()
            self.need_redraw = True
            self.need_clear = False
        for tab in self.fm.tabs.values():
            directory = tab.thisdir
            if directory:
                directory.load_content_if_outdated()
                directory.use()
        DisplayableContainer.draw(self)
        if self.draw_bookmarks:
            self._draw_bookmarks()
        elif self.draw_hints:
            self._draw_hints()
        elif self.draw_info:
            self._draw_info(self.draw_info)

    def finalize(self):
        if self.pager is not None and self.pager.visible:
            try:
                self.fm.ui.win.move(self.main_column.y, self.main_column.x)
            except curses.error:
                pass
        else:
            col_x = self.main_column.x
            col_y = self.main_column.y + self.main_column.target.pointer \
                - self.main_column.scroll_begin
            try:
                self.fm.ui.win.move(col_y, col_x)
            except curses.error:
                pass

    def _draw_bookmarks(self):
        self.columns[-1].clear_image(force=True)
        self.fm.bookmarks.update_if_outdated()
        self.color_reset()
        self.need_clear = True

        sorted_bookmarks = sorted(
            (
                item for item in self.fm.bookmarks
                if self.fm.settings.show_hidden_bookmarks or
                '/.' not in item[1].path
            ),
            key=lambda t: t[0].lower(),
        )

        hei = min(self.hei - 1, len(sorted_bookmarks))
        ystart = self.hei - hei

        maxlen = self.wid
        self.addnstr(ystart - 1, 0, "mark  path".ljust(self.wid), self.wid)

        whitespace = " " * maxlen
        for line, items in zip(range(self.hei - 1), sorted_bookmarks):
            key, mark = items
            string = " " + key + "   " + mark.path
            self.addstr(ystart + line, 0, whitespace)
            self.addnstr(ystart + line, 0, string, self.wid)

        self.win.chgat(ystart - 1, 0, curses.A_UNDERLINE)

    def _draw_info(self, lines):
        self.columns[-1].clear_image(force=True)
        self.need_clear = True
        hei = min(self.hei - 1, len(lines))
        ystart = self.hei - hei
        i = ystart
        whitespace = " " * self.wid
        for line in lines:
            if i >= self.hei:
                break
            self.addstr(i, 0, whitespace)
            self.addnstr(i, 0, line, self.wid)
            i += 1

    def _draw_hints(self):
        self.columns[-1].clear_image(force=True)
        self.need_clear = True
        hints = []
        for key, value in self.fm.ui.keybuffer.pointer.items():
            key = key_to_string(key)
            if isinstance(value, dict):
                text = '...'
            else:
                text = value
            if text.startswith('hint') or text.startswith('chain hint'):
                continue
            hints.append((key, text))
        hints.sort(key=lambda t: t[1])

        hei = min(self.hei - 1, len(hints))
        ystart = self.hei - hei
        self.addnstr(ystart - 1, 0, "key          command".ljust(self.wid), self.wid)
        try:
            self.win.chgat(ystart - 1, 0, curses.A_UNDERLINE)
        except curses.error:
            pass
        whitespace = " " * self.wid
        i = ystart
        for key, cmd in hints:
            string = " " + key.ljust(11) + " " + cmd
            self.addstr(i, 0, whitespace)
            self.addnstr(i, 0, string, self.wid)
            i += 1

    def click(self, event):
        if DisplayableContainer.click(self, event):
            return True
        direction = event.mouse_wheel_direction()
        if direction:
            self.main_column.scroll(direction)
        return False

    def resize(self, y, x, hei=None, wid=None):
        DisplayableContainer.resize(self, y, x, hei, wid)

    def poke(self):
        DisplayableContainer.poke(self)
