# TestReferences.py
#
# Copyright (C) 2011 Carlos Garcia Campos <carlosgc@gnome.org>
#
# 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 2 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
from __future__ import absolute_import, division, print_function

import os
import errno
from backends import get_backend, get_all_backends
from Config import Config
from Printer import get_printer
from Utils import get_document_paths_from_dir, get_skipped_tests, get_passwords

from InterruptibleQueue import InterruptibleQueue
from threading import Thread, RLock

class TestReferences:

    def __init__(self, docsdir, refsdir):
        self._docsdir = docsdir
        self._refsdir = refsdir
        self._skipped = get_skipped_tests(docsdir)
        self._passwords = get_passwords(docsdir)
        self.config = Config()
        self.printer = get_printer()
        self._total_tests = 1
        self._n_tests = 0

        self._queue = InterruptibleQueue()
        self._lock = RLock()

        try:
            os.makedirs(self._refsdir)
        except OSError as e:
            if e.errno != errno.EEXIST:
                raise
        except:
            raise

    def _get_backends(self):
        if self.config.backends:
            return [get_backend(name) for name in self.config.backends]

        return get_all_backends()

    def create_refs_for_file(self, filename):
        backends = self._get_backends()

        if filename in self._skipped:
            with self._lock:
                self._n_tests += len(backends)
            self.printer.print_default("Skipping test '%s'" % (os.path.join(self._docsdir, filename)))
            return

        refs_path = os.path.join(self._refsdir, filename)
        try:
            os.makedirs(refs_path)
        except OSError as e:
            if e.errno != errno.EEXIST:
                raise
        except:
            raise
        doc_path = os.path.join(self._docsdir, filename)

        password = self._passwords.get(filename)

        for backend in backends:
            if not self.config.force and backend.has_results(refs_path):
                with self._lock:
                    self._n_tests += 1
                self.printer.print_default("Results found, skipping '%s' for %s backend" % (doc_path, backend.get_name()))
                continue

            if backend.create_refs(doc_path, refs_path, password):
                backend.create_checksums(refs_path, self.config.checksums_only)
            with self._lock:
                self._n_tests += 1
            self.printer.printout_ln("[%d/%d] %s (%s): done" % (self._n_tests, self._total_tests, doc_path, backend.get_name()))

    def _worker_thread(self):
        while True:
            doc = self._queue.get()
            self.create_refs_for_file(doc)
            self._queue.task_done()

    def create_refs(self):
        docs, total_docs = get_document_paths_from_dir(self._docsdir)
        backends = self._get_backends()
        self._total_tests = total_docs * len(backends)

        if total_docs == 1:
            n_workers = 0
        else:
            n_workers = min(self.config.threads, total_docs)

        self.printer.printout_ln('Found %d documents' % (total_docs))
        self.printer.printout_ln('Backends: %s' % ', '.join([backend.get_name() for backend in backends]))
        self.printer.printout_ln('Process %d using %d worker threads' % (os.getpid(), n_workers))
        self.printer.printout_ln()

        if n_workers > 0:
            self.printer.printout('Spawning %d workers...' % (n_workers))

            for n_thread in range(n_workers):
                thread = Thread(target=self._worker_thread)
                thread.daemon = True
                thread.start()

            for doc in docs:
                self._queue.put(doc)

            self._queue.join()
        else:
            for doc in docs:
                self.create_refs_for_file(doc)
