# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4

import os
from threading import Thread
import time

from sqlitedict import SqliteDict

import db
import state
import settings
import update
import utils

import logging
logger = logging.getLogger(__name__)

class Downloads(Thread):

    def __init__(self):
        Thread.__init__(self)
        self.daemon = True
        self.start()
        self._dbpath = os.path.join(settings.data_path, 'transfers.db')
        self.transfers = SqliteDict(self._dbpath, tablename='transfers', autocommit=False)

    def download_updates(self):
        now = int(time.time())
        if now > settings.server.get('last_update_check', 0) + 24*60*60:
            settings.server['last_update_check'] = now
            update.download()
            state.user().export_library()
        if settings.preferences.get('sendDiagnostics') and \
              now > settings.server.get('last_send_diagnostics', 0) + 60*60 and \
              state.online:
            utils.send_debug()
            settings.server['last_send_diagnostics'] = now

    def download_next(self):
        import item.models
        self.download_updates()
        downloads = list(self.transfers.items())
        try:
            downloads.sort(key=lambda t: t[1].get('added'))
        except:
            pass
        for itemid, t in downloads:
            if state.shutdown:
                return False
            if itemid not in self.transfers:
                continue
            f = item.models.File.get(itemid)
            if f:
                del self.transfers[itemid]
                continue
            if t.get('added') and t.get('progress', -1) < 1:
                if 'users' not in t:
                    i = item.models.Item.get(itemid)
                    if not i:
                        del self.transfers[itemid]
                        continue
                    t['users'] = [u.id for u in i.users]
                for uid in t['users']:
                    if state.shutdown:
                        return False
                    if state.nodes.is_online(uid):
                        logger.debug('DOWNLOAD %s %s', i, uid)
                        if state.nodes.download(uid, i):
                            break
        return False

    def run(self):
        self.wait(10)
        while not state.shutdown:
            with db.session():
                self.download_next()
            self.wait(60)

    def join(self):
        self.transfers.commit()
        self.transfers.close(do_log=False)
        return Thread.join(self)

    def wait_online(self):
        while not state.online and not state.shutdown:
            self.wait(5)
        return not state.shutdown

    def wait(self, timeout):
        step = min(timeout, 1)
        while not state.shutdown and timeout > 0:
            time.sleep(step)
            timeout -= step