###################################################################################
# LQA Analyse: This module is used to fetch and analyse LAVA jobs/tests results.
#
# Copyright (C) 2015  Collabora Ltd.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.

# This library 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
# Lesser General Public License for more details.

# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  US
###################################################################################

import json
import os.path

from lqa_api.job import Job

class Analyse(object):

    def __init__(self, ids, conn):
        self._ids = ids
        self._conn = conn

        self._complete = { 'successful': [], 'failed': [] }
        self._incomplete = { 'bundles': [], 'no_bundles': [] }
        self._pending = { 'submitted': [], 'running': [] }
        self._canceled = { 'canceled': [], 'canceling': [] }

    def _find_jobs_status(self):
        for job_id in self._ids:
            job = Job(job_id, self._conn)
            if job.is_submitted():
                self._pending['submitted'].append(job)
            elif job.is_running():
                self._pending['running'].append(job)
            elif job.is_canceled():
                self._canceled['canceled'].append(job)
            elif job.is_canceling():
                self._canceled['canceling'].append(job)
            elif job.is_complete():
                self._find_successful_or_failed(job)
            else:
                if job.has_bundle():
                    self._incomplete['bundles'].append(job)
                else:
                    self._incomplete['no_bundles'].append(job)

    def _find_successful_or_failed(self, job):
        for test in job.tests:
            if test.results_failed:
                self._complete['failed'].append(job)
                # Return as soon as a failed test is found for the job.
                return
        # If no failed test in the job then it is successful.
        self._complete['successful'].append(job)

    def _find_missing_tests(self, job, test_run_ids):
        job_definition = json.loads(job.job_definition)
        test_def_list = []
        for actions in job_definition['actions']:
            if actions['command'] == 'lava_test_shell':
                params = actions['parameters']
                # Collect the test definitions from the job file so
                # that it can be compared with the final list of test runs.
                for td in params.get('testdef_repos', []):
                    test_def_list.append(
                        os.path.splitext(os.path.basename(td['testdef']))[0])

        for v in test_run_ids:
            # Skip the 'lava' test from the bundle
            if v == 'lava': continue
            test_def_list.remove(v)

        return test_def_list

    def sort_jobs_by_status(self):
        self._find_jobs_status()
        return {
            'complete': self._complete,
            'incomplete': self._incomplete,
            'pending': self._pending,
            'canceled': self._canceled,
            }
