#
#  Epour - A bittorrent client using EFL and libtorrent
#
#  Copyright 2012-2014 Kai Huuhko <kai.huuhko@gmail.com>
#
#  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, write to the Free Software
#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#  MA 02110-1301, USA.
#

import os
import logging

from libtorrent import add_torrent_params_flags_t

from efl.evas import EVAS_HINT_EXPAND, EVAS_HINT_FILL
from efl import elementary as elm
from efl.elementary.window import StandardWindow
from efl.elementary.button import Button
from efl.elementary.box import Box
from efl.elementary.frame import Frame
from efl.elementary.fileselector import Fileselector
from efl.elementary.fileselector_entry import FileselectorEntry
from efl.elementary.entry import Entry, markup_to_utf8, utf8_to_markup
from efl.elementary.check import Check
from efl.elementary.scroller import Scroller
from efl.elementary.spinner import Spinner
# from efl.elementary.object import ELM_SEL_TYPE_CLIPBOARD, \
#     ELM_SEL_FORMAT_TEXT

from Widgets import UnitSpinner

EXPAND_BOTH = EVAS_HINT_EXPAND, EVAS_HINT_EXPAND
EXPAND_HORIZ = EVAS_HINT_EXPAND, 0.0
FILL_BOTH = EVAS_HINT_FILL, EVAS_HINT_FILL
FILL_HORIZ = EVAS_HINT_FILL, 0.5

from efl.elementary.configuration import Configuration

elm_conf = Configuration()
scale = elm_conf.scale

log = logging.getLogger("epour.gui")


class TorrentSelector(StandardWindow):
    def __init__(self, parent, session, t_uri=None):
        StandardWindow.__init__(
            self, "epour", "Epour - Add Torrent",
            size=(scale * 400, scale * 400), autodel=True
            )

        self.add_dict = {}

        scrol = Scroller(
            self, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH
            )
        self.resize_object_add(scrol)

        box = Box(
            scrol, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH
            )

        scrol.content = box

        sf = Frame(
            box, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH,
            text=u"Select torrent file \u25BC", autocollapse=True
            )
        t_sel = Fileselector(
            sf, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH,
            expandable=False, buttons_ok_cancel=False, is_save=False
            )
        if elm.need_efreet():
            t_sel.mime_types_filter_append(
                ["application/x-bittorrent"], "Torrent files")
            t_sel.mime_types_filter_append(
                ["*"], "All files")

        if t_uri and os.path.isfile(t_uri):
            t_sel.selected = t_uri
            t_uri = None
        else:
            t_sel.path = os.path.expanduser("~")

        sf.content = t_sel
        box.pack_end(sf)
        sf.show()
        t_sel.show()

        m_entry = Entry(
            box, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_HORIZ,
            single_line=True, scrollable=True
            )
        m_entry.part_text_set("guide", "or enter magnet URI / info hash")
        if t_uri:
            m_entry.entry = utf8_to_markup(t_uri)
        box.pack_end(m_entry)
        m_entry.show()

        options = Frame(
            self, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_HORIZ,
            text=u"Options \u25BA", autocollapse=True, collapse=True
            )
        box.pack_end(options)
        options.show()

        def toggler(obj1, obj2):
            obj2.collapse_go(not obj1.collapse)
            if obj1.collapse:
                obj2.text = obj2.text.replace(u"\u25BA", u"\u25BC")
                obj1.text = obj1.text.replace(u"\u25BC", u"\u25BA")
            else:
                obj2.text = obj2.text.replace(u"\u25BC", u"\u25BA")
                obj1.text = obj1.text.replace(u"\u25BA", u"\u25BC")

        sf.callback_clicked_add(toggler, options)
        options.callback_clicked_add(toggler, sf)

        opt_box = Box(
            options, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH
            )
        options.content = opt_box

        def entry_cb(e, key):
            self.add_dict[key] = e.entry

        for n in "name", "trackerid":
            e = Entry(opt_box, size_hint_align=FILL_HORIZ)
            e.part_text_set("guide", n)
            e.callback_changed_user_add(entry_cb, n)
            opt_box.pack_end(e)
            e.show()

        def fs_cb(fs, key):
            self.add_dict[key] = fs.selected

        save_path = FsEntry(
            opt_box, size_hint_align=FILL_HORIZ, text="Save path",
            folder_only=True, expandable=False
            )
        save_path.path = session.conf.get("Settings", "storage_path")
        save_path.callback_changed_add(fs_cb, "save_path")
        opt_box.pack_end(save_path)
        save_path.show()

        self.add_dict["flags"] = \
            add_torrent_params_flags_t.flag_apply_ip_filter + \
            add_torrent_params_flags_t.flag_update_subscribe + \
            add_torrent_params_flags_t.flag_auto_managed

        def option_flag_cb(c, flag):
            self.add_dict["flags"] = self.add_dict["flags"] ^ flag

        for name, flag in add_torrent_params_flags_t.names.items():
            if name == "flag_auto_managed" or name == "flag_update_subscribe":
                continue
            c = Check(
                opt_box, size_hint_align=(0.0, 0.5),
                text=" ".join(name.split("_")[1:]).capitalize(),
                state=self.add_dict["flags"] & int(flag)
                )
            c.callback_changed_add(option_flag_cb, int(flag))
            opt_box.pack_end(c)
            c.show()

        INT_MAX = 2147483647

        def spin_cb(s, key):
            self.add_dict[key] = s.value

        for n in (
            "max_uploads", "max_connections"
                ):
            s = Spinner(
                opt_box, size_hint_align=FILL_HORIZ,
                text=n.replace("_", " ").capitalize(),
                min_max=(0, INT_MAX), label_format=n + ": %0.f"
                )
            s.callback_changed_add(spin_cb, n)
            opt_box.pack_end(s)
            s.show()

        for n in (
            "upload_limit", "download_limit"
                ):
            s = UnitSpinner(opt_box, "B/s", 1024, UnitSpinner.binary_prefixes)
            s.size_hint_weight = EXPAND_HORIZ
            s.size_hint_align = FILL_HORIZ
            s.set_value(0)
            s.callback_changed_add(
                lambda x, y: self.add_dict.__setitem__(n, y)
                )
            s.spinner.label_format = n + ": %0.f"
            opt_box.pack_end(s)
            s.show()

        # TODO:
        # list(strings) trackers (list(entry))
        # list(tuple(str host, int port), ...) dht_nodes
        # storage_mode_t storage_mode
        # list(int) file_priorities (list(spinner))

        opt_box.show()

        bbox = Box(
            box, size_hint_weight=EXPAND_HORIZ,
            size_hint_align=FILL_HORIZ, horizontal=True
            )

        ok_btn = Button(bbox, text="Ok", size_hint_align=(1.0, 0.5))
        bbox.pack_end(ok_btn)
        ok_btn.show()

        cancel_btn = Button(bbox, text="Cancel", size_hint_align=(1.0, 0.5))
        bbox.pack_end(cancel_btn)
        cancel_btn.show()

        bbox.show()

        box.pack_end(bbox)
        box.show()
        scrol.show()

        def add_torrent_cb(btn, t_sel, m_entry, session, add_dict):
            f = t_sel.selected
            m = m_entry.entry

            if f and os.path.isfile(f):
                log.debug("Adding file: %s", f)
                session.add_torrent_from_file(add_dict, f)
                self.delete()
            elif m:
                m = markup_to_utf8(m)
                if m.startswith("magnet:"):
                    log.debug("Adding torrent from magnet link: %s", m)
                    session.add_torrent_from_magnet(add_dict, m)
                else:
                    log.debug("Adding torrent from info hash: %s", m)
                    session.add_torrent_from_hash(add_dict, m)
                self.delete()
            else:
                return

        ok_btn.callback_clicked_add(
            add_torrent_cb, t_sel, m_entry, session, self.add_dict
            )
        cancel_btn.callback_clicked_add(lambda x: self.delete())

        self.show()


class FsEntry(Fileselector, FileselectorEntry):
    def __init__(self, parent, **kwargs):
        FileselectorEntry.__init__(self, parent, **kwargs)
