###################################################################################
# LAVA QA tool
# Copyright (C) 2016 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
###################################################################################

from lqa_api.job import Job, JobError
from lqa_api.exit_codes import SUCCESS, APPLICATION_ERROR, OPERATION_FAILED
from lqa_tool.commands import Command
from lqa_tool.settings import lqa_logger

class DiffResultsCmd(Command):

    def __init__(self, args):
        Command.__init__(self, args)
        try:
            self.job1 = Job(self.args.job1_id, self.server)
            self.job2 = Job(self.args.job2_id, self.server)
        except JobError as err:
            lqa_logger.error("lqa diff: {} {}".format(err.code, err.msg))
            exit(APPLICATION_ERROR)
        self._exit_code = SUCCESS 

    def run(self):
        print '(1)', self.job1
        print '(2)', self.job2
        for test_job1 in self.job1.tests:
            # Include lava tests if --infra passed.
            if test_job1.name == 'lava' and not self.args.infra:
                continue

            # Filter job2 tests available in job1.
            job2tests = filter(lambda t: t.name == test_job1.name, self.job2.tests)

            # Show if there are missing tests in job2 from job1.
            if not job2tests:
                print "!! {}".format(test_job1.name)
                continue

            for test_job2 in job2tests:
                self._is_test_name_printed = False
                # Iterate over the tests results for both jobs and check diffs.
                for tc_job1 in test_job1.results:
                    for tc_job2 in test_job2.results:
                        self._diff_jobs(tc_job1, tc_job2, test_job1, test_job2)
        # Exit
        exit(self._exit_code)

    def _diff_jobs(self, tc_job1, tc_job2, test_job1, test_job2):

        def _print_diff(tj1, tj2, tc1, result1, tc2, result2):
            # Make sure to print the test name only once for all the results.
            if not self._is_test_name_printed:
                print "1:", tj1
                print "2:", tj2
                self._is_test_name_printed = True
                # Set to FAILED only once.
                if self._exit_code == SUCCESS:
                    self._exit_code = OPERATION_FAILED
            print " 1> {}:{}".format(tc1, result1)
            print " 2> {}:{}".format(tc2, result2)

        if tc_job1['test_case_id'] == tc_job2['test_case_id']:
            # Only print results if there are differences.
            if tc_job1['result'] != tc_job2['result']:
                _print_diff(test_job1, test_job2,
                            tc_job1['test_case_id'], tc_job1['result'].upper(),
                            tc_job2['test_case_id'], tc_job2['result'].upper())
            else:
                # If no 'results', check for measurements diffs.
                m1 = tc_job1.get('measurement', False)
                m2 = tc_job2.get('measurement', False)
                u1 = tc_job1.get('units', None)
                u2 = tc_job2.get('units', None)
                if (m1 and m2) and (u1 == u2) and (m1 != m2):
                    _print_diff(test_job1, test_job2,
                                tc_job1['test_case_id'], "{}{}".format(m1, u1),
                                tc_job2['test_case_id'], "{}{}".format(m2, u2))
