#!/usr/bin/env python
# -*- coding: utf-8 -*-

#  Copyright (c) 2015 Lingaro


import datetime
import traceback

from robot.api import logger

from .utils import get_first


class TestResultManager(object):

    def _build_test_result_data(self, test_case_id, build, verdict, date=None, tester=None,
                                test_set_id=None, notes=None, duration=None):
        """
        :param test_case_ID:
        :param verdict:
        :param build:
        :param date:
        :param tester:
        :param test_set:
        :param notes:
        :param duration:
        :return:
        """
        test_case = self._get_test_case_by_id(test_case_id)
        result = dict(
            TestCase=test_case.ref,
            Build=build,
            Verdict=verdict,
            Date=date or datetime.datetime.now().isoformat()
        )
        if tester:
            user = self._get_user_by_name(tester)
            result['Tester'] = user.ref
        if test_set_id:
            test_set = self._get_test_set_by_id(test_set_id)
            result['TestSet'] = test_set.ref
        if notes:
            result['Notes'] = notes
        if duration:
            result['Duration'] = duration
        return result

    def add_test_result(self, test_case_id, build, verdict, notes=None, attachment_list=None, date=None, tester=None,
                        test_set_id=None, duration=None, number_of_retries=3):
        """
        Adds a new Test Result to Test Case provided with FormatterID passed as first (obligatory) parameter.

        It takes 3 mandatory parameters `test_case_id` (FormattedID of test case - if list is provided it takes first
        element from list), `build` and `verdict` (allowed values are Fail or Pass).
        The last required for the test result creation parameter is `date` parameter. If it is not provided directyle
        it is set to the current datetime.

        Method takes 6 optional parameters: `notes`, `attachment_list` (a list of paths to files - absolute or relative),
        `tester` (name of the user), `test_set_id` (FormattedID of TestSet object), `duration` and `number_of_retries`.

        Example usage:
        | # minimal information |
        |Add Test Result | TC5001 | BUILD | Pass |
        | # standard usage |
        |Add Test Result | TC5001 | BUILD | Pass | Very complex test | ${attachment_list} |

        """
        logger.info(u"""Add test result:
        FormattedID: {test_case_id}
        Build: {build}
        Verdict: {verdict}
        Date: {date}
        Tester: {tester}
        TestSet: {test_set_id}
        Notes: {notes}
        Duration: {duration}
        Number of retries: {number_of_retries}
        Attachment_list: {attachment_list}""".format(
            test_case_id=test_case_id,
            build=build,
            verdict=verdict,
            date=date,
            tester=tester,
            test_set_id=test_set_id,
            notes=notes,
            duration=duration,
            number_of_retries=number_of_retries,
            attachment_list=attachment_list
        ))
        test_case_id = get_first(test_case_id)
        connection = self._get_rally_connection()
        number_of_retries = int(number_of_retries)
        test_result_data = self._build_test_result_data(
            test_case_id, build, verdict, date=date, tester=tester, test_set_id=test_set_id,
            notes=notes, duration=duration
        )
        iteration = 0
        while iteration < number_of_retries:
            try:
                test_result = connection.create('TestCaseResult', test_result_data)
                self._add_attachments(test_result, attachment_list)
                break
            except Exception as e:
                logger.warn("An error occurred")
                logger.warn(traceback.format_exc())
                iteration += 1
                if iteration == number_of_retries:
                    raise e