# -*- coding: utf-8 -*-
import logging
from multiprocessing.dummy import Pool
from os.path import dirname, exists, join
from shutil import rmtree
from startrek_client import Startrek
from threading import Thread
from time import sleep
import traceback as tb
from Queue import Queue

from const import CONFIG, SECRET
from errs import NoReportsError
from reports.ta_task import TATask, task_worker
from service import delete_old_revisions, delete_old_tasks
from utils import send_mail

logger = logging.getLogger(__name__)


def check_queue(test_keys=None):
    debug = True if test_keys else False

    try:
        st_client = Startrek(useragent='', token=SECRET['token'])
        if test_keys:
            issues = [st_client.issues[key] for key in test_keys]
        else:
            issues = st_client.issues.find(query=CONFIG['ST_QUERY'], order=['+created'])

    except:
        logger.exception('Oops in check_queue!')
        if not debug:
            send_mail(from_='%s@yandex-team.ru' % SECRET['PASSPORT']['login'], password=SECRET['PASSPORT']['password'],
                      to=['vbatraev@yandex-team.ru'], subject=u'Error in check_queue', message=tb.format_exc())
        issues = []

    tasks = []
    for issue in issues:
        try:
            task = TATask(issue, debug)
            tasks.append(task)
        except NoReportsError as exc:
            logger.error('%s: %s', issue.key, exc.message)

        except:
            logger.exception('%s: Oops!', issue.key)
            if not debug:
                issue.comments.create(text=u'Что-то сломалось...<{Подробнее:\n%%%%\n%s\n%%%%\n}>' % tb.format_exc(),
                                      summonees=['vbatraev'])
                issue.transitions['need_info'].execute()

            issue_path = join(dirname(dirname(__file__)), issue.key)
            if exists(issue_path):
                rmtree(issue_path)

    return tasks


class ServiceThread(Thread):
    def __init__(self):
        super(ServiceThread, self).__init__()

    def run(self):
        try:
            delete_old_revisions()
        except:
            send_mail(from_='%s@yandex-team.ru' % SECRET['PASSPORT']['login'], password=SECRET['PASSPORT']['password'],
                      to=['vbatraev@yandex-team.ru'], subject=u'Error in delete_old_revisions', message=tb.format_exc())

        while True:
            try:
                delete_old_tasks()
            except:
                send_mail(from_='%s@yandex-team.ru' % SECRET['PASSPORT']['login'],
                          password=SECRET['PASSPORT']['password'], to=['vbatraev@yandex-team.ru'],
                          subject=u'Error in delete_old_tasks', message=tb.format_exc())

            sleep(60 * 60 * 24)


class TasksPool(Thread):
    def __init__(self, name, limit):
        super(TasksPool, self).__init__()
        self.name = name
        self.queue = Queue()
        self.pool = Pool(limit)

        self.limit = limit
        self.issues = []
        self.current_count = 0

    def generate_tasks(self):
        while True:
            task = self.queue.get()
            self.issues.append(task.issue.key)
            self.current_count += 1

            logger.info('%s-pool: yield %s (%i/%i busy)', self.name, task.issue.key, self.current_count, self.limit)
            yield task

    def run(self):
        for task in self.pool.imap_unordered(task_worker, self.generate_tasks()):
            self.issues.remove(task.issue.key)
            self.current_count -= 1
            logger.info('%s-pool: %s completed (%i/%i busy)', self.name, task.issue.key, self.current_count, self.limit)

    def is_full(self):
        return self.current_count >= self.limit


def run_robot():
    send_mail(from_='%s@yandex-team.ru' % SECRET['PASSPORT']['login'], password=SECRET['PASSPORT']['password'],
              to=['vbatraev@yandex-team.ru', 'leroy@yandex-team.ru'],
              subject=u'Робот запущен!', message=u'Выгрузка исходников для сборки Техноаудита')

    logger.info('Go!')

    service_thread = ServiceThread()
    service_thread.start()

    light, hard = TasksPool('LIGHT', 10), TasksPool('HARD', 5)
    light.start()
    hard.start()

    while True:
        for task in check_queue():
            pool = hard if task.is_hard() else light
            if task.issue.key not in pool.issues:
                if not pool.is_full():
                    if not task.was_in_progress:
                        task.issue.transitions['start_progress'].execute()
                    else:
                        logger.info('%s: was inProgress', task.issue.key)
                    pool.queue.put(task)

                else:
                    logger.info('%s-pool: is full', pool.name)

        sleep(60 * 1.5)


def run_tasks(*test_keys):
    if not test_keys:
        raise Exception('test_keys not set')

    for task in check_queue(test_keys):
        try:
            task_worker(task)
        except:
            logger.exception('%s: Oops!', task.issue.key)
            break
