#!/usr/bin/python3
#
#  Epour - A bittorrent client using EFL and libtorrent
#
#  Copyright 2012-2017 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 sys
from argparse import ArgumentParser
parser = ArgumentParser(description="A BitTorrent client.")
parser.add_argument(
    '-v', '--verbose', action="count", help="max is -vvv")
parser.add_argument(
    '--disable-add-dialog', action="store_true",
    help="Torrents to be added from arguments don't open a dialog")
parser.add_argument(
    'torrents', nargs="*", help="file path, magnet uri, or info hash",
    metavar="TORRENT")
args = parser.parse_args()

from efl.dbus_mainloop import DBusEcoreMainLoop

import dbus
ml = DBusEcoreMainLoop()
dbus.set_default_main_loop(ml)
import dbus.service
bus = dbus.SessionBus()

try:
    dbo = bus.get_object("net.launchpad.epour", "/net/launchpad/epour")
except dbus.exceptions.DBusException:
    pass
else:
    for f in args.torrents:
        print("Sending {0} via dbus".format(f))
        if args.disable_add_dialog:
            dbo.AddTorrentWithoutDialog(
                f, dbus_interface="net.launchpad.epour")
        else:
            dbo.AddTorrent(f, dbus_interface="net.launchpad.epour")
    sys.exit()

import os
if sys.hexversion >= 0x030000F0:
    from configparser import ConfigParser as SafeConfigParser
else:
    from ConfigParser import SafeConfigParser

import logging

from xdg.BaseDirectory import save_data_path, save_config_path, \
    load_config_paths

from .session import Session
from .gui import MainInterface


class Epour(object):

    def __init__(self):
        self.log = self.setup_log()
        self.log.debug("Logging started")
        self.conf = self.setup_conf()

        session = self.session = Session(self.conf, self._quit_cb)
        session.load_state()

        self.gui = MainInterface(self, session)

        self.dbusname = dbus.service.BusName(
            "net.launchpad.epour", dbus.SessionBus()
        )
        self.dbo = EpourDBus(session, self.gui, self.conf)

        self.session.load_torrents()

        for t in args.torrents:
            if (not args.disable_add_dialog) and \
                    self.conf.getboolean("Settings", "add_dialog_enabled"):
                self.gui.add_torrent(t)
            else:
                self.session.add_torrent_with_uri(t)

    def setup_log(self):
        log_level = logging.ERROR
        if args.verbose:
            log_level -= 10 * args.verbose

        log = logging.getLogger("epour")
        log.propagate = False
        log.setLevel(log_level)

        ch = logging.StreamHandler()
        ch_formatter = logging.Formatter(
            '%(name)s: [%(levelname)s] %(message)s (%(filename)s: %(lineno)d)')
        ch.setFormatter(ch_formatter)
        ch.setLevel(log_level)
        log.addHandler(ch)

        fh = logging.FileHandler(
            os.path.join(save_data_path("epour"), "epour.log"))
        fh_formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        fh.setFormatter(fh_formatter)
        fh.setLevel(logging.ERROR)
        log.addHandler(fh)

        return log

    def setup_conf(self):
        conf = SafeConfigParser({
            "storage_path": os.path.expanduser(
                os.path.join("~", "Downloads")
            ),
            "move_completed_path": os.path.expanduser(
                os.path.join("~", "Downloads")
            ),
            "move_completed_enabled": str(False),
            "confirm_exit": str(False),
            "add_dialog_enabled": str(True),
            "delete_original": str(False),
            "listen_low": str(0),
            "listen_high": str(0),
        })

        for p in load_config_paths("epour"):
            if conf.read(os.path.join(p, "epour.conf")):
                break

        if not conf.has_section("Settings"):
            conf.add_section("Settings")

        return conf

    def save_conf(self):
        conf_path = os.path.join(save_config_path("epour"), "epour.conf")
        if sys.hexversion >= 0x030000F0:
            with open(conf_path, 'w') as configfile:
                self.conf.write(configfile)
        else:
            with open(conf_path, 'wb') as configfile:
                self.conf.write(configfile)

    def _quit_cb(self):
        self.gui.stop_mainloop()


class EpourDBus(dbus.service.Object):

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

    def __init__(self, session, gui, conf):
        self.session = session
        self.gui = gui
        self.conf = conf
        dbus.service.Object.__init__(
            self, dbus.SessionBus(),
            "/net/launchpad/epour", "net.launchpad.epour")

        self.props = {
        }

    @dbus.service.method(dbus_interface='net.launchpad.epour',
                         in_signature='s', out_signature='')
    def AddTorrent(self, t):
        self.log.info("Adding %s from dbus" % t)
        try:
            if self.conf.getboolean("Settings", "add_dialog_enabled"):
                self.gui.add_torrent(t)
            else:
                self.session.add_torrent_with_uri(t)
        except Exception:
            self.log.exception("Error while adding torrent from dbus")

    @dbus.service.method(dbus_interface='net.launchpad.epour',
                         in_signature='s', out_signature='')
    def AddTorrentWithoutDialog(self, t):
        self.log.info("Adding %s from dbus" % t)
        try:
            self.session.add_torrent_with_uri(t)
        except Exception:
            self.log.exception("Error while adding torrent from dbus")

if __name__ == "__main__":
    efllog = logging.getLogger("efl")
    efllog.setLevel(logging.INFO)
    efllog_formatter = logging.Formatter(
        '%(name)s: [%(levelname)s] %(message)s')
    efllog_handler = logging.StreamHandler()
    efllog_handler.setFormatter(efllog_formatter)
    efllog.addHandler(efllog_handler)

    epour = Epour()
    epour.gui.run_mainloop()
    try:
        epour.save_conf()
    except Exception:
        epour.log.exception("Saving conf failed")

    logging.shutdown()
