# Copyright (C) 2014 Brian Marshall
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

from operator import attrgetter

from gi.repository import Gio
import urwid

from sisko.widgets import Dialog, OverlayStack, PathBar, FileItem

# Vim-like cursor movement.
urwid.command_map['k'] = 'cursor up'
urwid.command_map['j'] = 'cursor down'
urwid.command_map['h'] = 'cursor left'
urwid.command_map['l'] = 'cursor right'

class Application:
    """
    Main application class.
    """

    _PALETTE = [('dialog', 'black', 'light gray'),
                ('focused', 'white', 'dark blue'),
                ('folder', 'bold', ''),
                ('folder focused', 'white, bold', 'dark blue'),
                ('footer', 'light gray', 'dark gray'),
                ('footer key', 'white, bold', 'black'),
                ('path-bar', 'white', 'black'),
                ('path-bar current', 'white, bold', 'dark gray')]

    _FOOTER = [('footer key', " Alt+H "), " ", _("Hidden Files"), "  ",
               ('footer key', " Q "), " ", _("Quit")]

    def __init__(self):
        self._path_bar = PathBar()
        self._files = urwid.SimpleFocusListWalker([])
        self._toplevel = OverlayStack(urwid.Frame(
            urwid.ListBox(self._files),
            header=self._path_bar,
            footer=urwid.AttrMap(urwid.Text(self._FOOTER), 'footer')))
        self._show_hidden = False

    def run(self, folder: Gio.File):
        """
        Run the application, opening the given folder.
        """
        self._open(folder)
        main = urwid.MainLoop(self._toplevel, self._PALETTE,
                              unhandled_input=self._unhandled_input)
        main.screen.set_terminal_properties(bright_is_bold=False)
        main.run()

    def _open(self, folder: Gio.File):
        """
        Open a folder.
        """
        children = folder.enumerate_children(
            ','.join([Gio.FILE_ATTRIBUTE_STANDARD_IS_HIDDEN,
                      Gio.FILE_ATTRIBUTE_STANDARD_IS_BACKUP,
                      Gio.FILE_ATTRIBUTE_STANDARD_NAME,
                      FileItem.FILE_ATTRIBUTES]),
            Gio.FileQueryInfoFlags.NONE, None)
        self._path_bar.location = folder
        del self._files[:]
        for info in children:
            if self._show_hidden or not (info.get_is_hidden() or
                                         info.get_is_backup()):
                self._files.append(FileItem(folder.get_child(info.get_name()),
                                            info))
        list.sort(self._files, key=attrgetter('name_key'))

    def _open_focused(self):
        """
        Open the focused folder.
        """
        focus = self._files.get_focus()[0]
        if (focus is not None and
                focus.info.get_file_type() == Gio.FileType.DIRECTORY):
            self._open(focus.file)

    def _trash_focused(self):
        """
        Move the focused file to the Trash.
        """
        focus = self._files.get_focus()[0]
        if focus is None:
            return
        dialog = Dialog(
            _("Are you sure you want to move \"{}\" to the Trash?").format(
                focus.info.get_display_name()),
            [(_("Cancel"), 'cancel'), (_("Move to Trash"), 'trash')])
        def on_response(response_id):
            if response_id == 'trash':
                focus.file.trash(None)
                del self._files[self._files.index(focus)]
        self._toplevel.show_dialog(dialog, on_response)

    def _unhandled_input(self, key):
        """
        Handle application key commands.
        """
        if urwid.command_map[key] == 'cursor left':
            # Open previous folder in the path.
            if self._path_bar.previous is not None:
                self._open(self._path_bar.previous)
        elif urwid.command_map[key] == 'cursor right':
            # Open next folder in the path.
            if self._path_bar.next is not None:
                self._open(self._path_bar.next)
        elif urwid.command_map[key] == 'activate':
            self._open_focused()
        elif key == 'delete':
            self._trash_focused()
        elif key == 'meta h':
            self._show_hidden = not self._show_hidden
            self._open(self._path_bar.location)
        elif key in ('Q', 'q'):
            raise urwid.ExitMainLoop
