# 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 LICENSE for more details.
#
# Copyright: Red Hat, Inc. 2016
# Author: Cleber Rosa <crosa@redhat.com>
"""
Human result UI
"""

from avocado.core import output
from avocado.core.output import LOG_UI
from avocado.core.plugin_interfaces import JobPost, JobPre, ResultEvents


class Human(ResultEvents):

    """
    Human result UI
    """

    name = 'human'
    description = "Human Interface UI"

    def __init__(self, config):
        self.__throbber = output.Throbber()
        stdout_claimed_by = config.get('stdout_claimed_by', None)
        self.owns_stdout = not stdout_claimed_by
        self.runner = config.get('run.test_runner')

    def pre_tests(self, job):
        if not self.owns_stdout:
            return
        LOG_UI.info("JOB ID     : %s", job.unique_id)
        # TODO: this is part of the legacy implementation of the
        # replay plugin and should be removed soon.
        replay_enabled = replay_source_job = job.config.get("replay_sourcejob", False)
        # The "avocado replay" plugin sets a different namespace
        if not replay_source_job:
            replay_enabled = job.config.get("job.replay.enabled")
            replay_source_job = job.config.get("job.replay.source_job_id")
        if replay_enabled and replay_source_job:
            LOG_UI.info("SRC JOB ID : %s", replay_source_job)
        LOG_UI.info("JOB LOG    : %s", job.logfile)

    def start_test(self, result, state):
        if not self.owns_stdout:
            return
        if "name" in state:
            name = state["name"]
            uid = name.str_uid
            name = name.name + name.str_variant
        else:
            name = "<unknown>"
            uid = '?'
        if self.runner == 'nrunner':
            LOG_UI.debug(' (%s/%s) %s: STARTED', uid, result.tests_total, name)
        else:
            LOG_UI.debug(' (%s/%s) %s:  ', uid, result.tests_total, name,
                         extra={"skip_newline": True})

    def test_progress(self, progress=False):
        if not self.owns_stdout:
            return
        if progress:
            color = output.TERM_SUPPORT.PASS
        else:
            color = output.TERM_SUPPORT.PARTIAL
        if self.runner == 'runner':
            LOG_UI.debug('%s%s%s', color, self.__throbber.render(),
                         output.TERM_SUPPORT.ENDC, extra={"skip_newline": True})

    def get_colored_status(self, status, extra=None):
        out = (output.TERM_SUPPORT.MOVE_BACK + output.TEST_STATUS_MAPPING[status] +
               status)
        if extra:
            if len(extra) > 255:
                extra = extra[:255] + '...'
            extra = extra.replace('\n', '\\n')
            out += ": " + extra
        out += output.TERM_SUPPORT.ENDC
        return out

    def end_test(self, result, state):
        if not self.owns_stdout:
            return
        status = state.get("status", "ERROR")
        if status == "TEST_NA":
            status = "SKIP"
        duration = (" (%.2f s)" % state.get('time_elapsed', -1)
                    if status != "SKIP"
                    else "")
        if self.runner == 'nrunner':
            if "name" in state:
                name = state["name"]
                uid = name.str_uid
                name = name.name + name.str_variant
            else:
                name = "<unknown>"
                uid = '?'

            msg = self.get_colored_status(status, state.get("fail_reason", None))
            LOG_UI.debug(' (%s/%s) %s:  ', uid, result.tests_total, name,
                         extra={"skip_newline": True})
        else:
            msg = self.get_colored_status(status, state.get("fail_reason", None))
        LOG_UI.debug(msg + duration)

    def post_tests(self, job):
        if not self.owns_stdout:
            return

        if job.interrupted_reason is not None:
            LOG_UI.info(job.interrupted_reason)

        if job.status == 'PASS':
            LOG_UI.info("RESULTS    : PASS %d | ERROR %d | FAIL %d | SKIP %d | "
                        "WARN %d | INTERRUPT %s | CANCEL %s", job.result.passed,
                        job.result.errors, job.result.failed, job.result.skipped,
                        job.result.warned, job.result.interrupted,
                        job.result.cancelled)


class HumanJob(JobPre, JobPost):

    """
    Human result UI
    """

    name = 'human'
    description = "Human Interface UI"

    def pre(self, job):
        pass

    def post(self, job):
        if job.status == 'PASS':
            if not job.config.get('stdout_claimed_by', None):
                LOG_UI.info("JOB TIME   : %.2f s", job.time_elapsed)
