# pylint: disable=C0103

"""This class knows how to understand annotations.

    Here are a list of the currently supported annotations:

    @@@BUILD_STEP <stepname>@@@
    Add a new step <stepname>. End the current step, marking with last available
    status.

    @@@STEP_LINK@<label>@<url>@@@
    Add a link with label <label> linking to <url> to the current stage.

    @@@STEP_WARNINGS@@@
    Mark the current step as having warnings (oragnge).

    @@@STEP_FAILURE@@@
    Mark the current step as having failed (red).

    @@@STEP_EXCEPTION@@@
    Mark the current step as having exceptions (magenta).

    @@@STEP_CLEAR@@@
    Reset the text description of the current step.

    @@@STEP_SUMMARY_CLEAR@@@
    Reset the text summary of the current step.

    @@@STEP_TEXT@<msg>@@@
    Append <msg> to the current step text.

    @@@STEP_SUMMARY_TEXT@<msg>@@@
    Append <msg> to the step summary (appears on top of the waterfall).

    @@@HALT_ON_FAILURE@@@
    Halt if exception or failure steps are encountered (default is not).

    @@@HONOR_ZERO_RETURN_CODE@@@
    Honor the return code being zero (success), even if steps have other results.

    Deprecated annotations:
    TODO(bradnelson): drop these when all users have been tracked down.

    @@@BUILD_WARNINGS@@@
    Equivalent to @@@STEP_WARNINGS@@@

    @@@BUILD_FAILED@@@
    Equivalent to @@@STEP_FAILURE@@@

    @@@BUILD_EXCEPTION@@@
    Equivalent to @@@STEP_EXCEPTION@@@

    @@@link@<label>@<url>@@@
    Equivalent to @@@STEP_LINK@<label>@<url>@@@
"""

import re

from twisted.internet import defer
from twisted.internet import error
from twisted.python import failure
from twisted.python import log as logging

from buildbot.process import buildstep
from buildbot.process import results
from buildbot.process import logobserver

from buildbot.plugins import util

from buildbot.util import asyncSleep
from buildbot.util.misc import deferredLocked

if False:  # for debugging
    debuglog = logging.msg
else:
    debuglog = lambda m: None

class AnnotatedBuildStep(buildstep.BuildStep):

    def  __init__(self, parent_step, *args, **kwargs):
        self.parent_step = parent_step
        buildstep.BuildStep.__init__(self, *args, **kwargs)

        # Step is really unpredictable
        self.useProgress = False

        self.build = self.parent_step.build
        self.master = self.parent_step.build.master
        self.worker = self.parent_step.worker

        self.stdio_log = None

        self._loglines = []
        self._logLock = defer.DeferredLock()

        self._request_finish = False

    @defer.inlineCallbacks
    def addStep(self):
        debuglog("AnnotatedBuildStep: adding step '%s': buildid=%s" % (
                    self.name, self.build.buildid))
        yield buildstep.BuildStep.addStep(self)
        # Put ourselves into a list of processed steps of the build object.
        self.build.executedSteps.append(self)
        # Init result to SUCCESS by default.
        self.results = results.SUCCESS
        self.description = [self.name]
        self.stdio_log = yield self.addLog('stdio')

        debuglog("AnnotatedBuildStep: added step '%s': stepid=%s, buildid=%s" % (
                    self.name, self.stepid, self.build.buildid))


    @defer.inlineCallbacks
    def finishStep(self):
        hidden = False
        debuglog("AnnotatedBuildStep: finish step '%s': stepid=%s, buildid=%s, results=%s" % (
                    self.name, self.stepid, self.build.buildid, self.results))
        yield self.master.data.updates.finishStep(self.stepid, self.results,
                                                  hidden)
        # finish unfinished logs
        yield self.finishUnfinishedLogs()

    @defer.inlineCallbacks
    def startStep(self, remote):
        try:
            yield self.addStep()

            try:
                self.realUpdateSummary()

                self._running = True
                self.results = yield self.run()
            finally:
                self._running = False

        except buildstep.BuildStepCancelled:
            self.results = results.CANCELLED

        except buildstep.BuildStepFailed:
            self.results = results.FAILURE

        except error.ConnectionLost:
            self.results = results.RETRY

        except Exception:
            self.results = results.EXCEPTION
            why = failure.Failure()
            logging.err(why, "AnnotatedBuildStep.failed; traceback follows")
            yield self.addLogWithFailure(why)

        finally:
            # update the summary one last time, make sure that completes,
            # and then don't update it any more.
            self.realUpdateSummary()
            yield self.realUpdateSummary.stop()

            # Update step status in the database.
            yield self.finishStep()

        debuglog("AnnotatedBuildStep::startStep() completed '%s': "
                 "stepid=%s, buildid=%s, results=%s" % (
                 self.name, self.stepid, self.build.buildid, self.results))

    def requestFinish(self, status=None):
        debuglog("AnnotatedBuildStep::requestFinish(%r): '%s': "
                 "stepid=%s, buildid=%s, results=%r" % (
                 status, self.name, self.stepid, self.build.buildid, self.results))
        # Update the current step status with the worst result.
        if status is not None:
            self.updateStatus(status)
        self._request_finish = True

    def setStepText(self, text=None):
        if text is not None:
            if self.description is not None:
                self.description.append(text)
        else:
            self.description = []

        self.updateSummary()

    def setStepSummary(self, text=None):
        if text is not None:
            if self.descriptionDone is not None:
                self.descriptionDone.append(text)
        else:
            self.descriptionDone = []

        self.updateSummary()

    @deferredLocked("_logLock")
    def _flushLogs(self):
        if self._loglines:
            ll = "".join(self._loglines)
            self._loglines = []
            self.stdio_log.addStdout(ll)
        return defer.succeed(None)

    @deferredLocked("_logLock")
    def _addLogs(self, text):
        if text is not None:
            self._loglines.append(text)
        return defer.succeed(None)

    @defer.inlineCallbacks
    def run(self):
        # Save previously collected log lines.
        yield self._flushLogs()

        while not self._request_finish:
            # Sleep for .1 second. Let arrive more logs.
            yield asyncSleep(.1)
            if self._loglines:
                yield self._flushLogs()

        # and the last one time.
        if self._loglines:
            yield self._flushLogs()

        debuglog("AnnotatedBuildStep::run() exiting '%s' step: "
                 "stepid=%s, buildid=%s, results=%s" % (
                 self.name, self.stepid, self.build.buildid, self.results))

        return self.results

    @defer.inlineCallbacks
    def scheduleStdout(self, text):
        if text is None:
            return

        # Not running yet, just store a log line.
        if not self._running:
            self._loglines.append(text)
            return

        # Already executed, add the log line with locking.
        yield self._addLogs(text=text)

    def updateStatus(self, status):
        self.results = results.worst_status(self.results, status)


ALL_COMMANDS = list(range(11))
STEP_LINK, STEP_WARNINGS, STEP_FAILURE, STEP_EXCEPTION, HALT_ON_FAILURE, HONOR_ZERO_RC, STEP_CLEAR, STEP_SUMMARY_CLEAR, STEP_TEXT, STEP_SUMMARY_TEXT, BUILD_STEP = ALL_COMMANDS

class AnnotatedCommand(buildstep.ShellMixin, buildstep.BuildStep):
    """Buildbot command that knows how to display annotations."""

    _re_step_link           = re.compile(r'^@@@(STEP_LINK|link)@(?P<link_label>.*)@(?P<link_url>.*)@@@', re.M)
    _re_step_warnings       = re.compile(r'^@@@(STEP_WARNINGS|BUILD_WARNINGS)@@@', re.M)
    _re_step_failure        = re.compile(r'^@@@(STEP_FAILURE|BUILD_FAILED)@@@', re.M)
    _re_step_exception      = re.compile(r'^@@@(STEP_EXCEPTION|BUILD_EXCEPTION)@@@', re.M)
    _re_halt_on_failure     = re.compile(r'^@@@HALT_ON_FAILURE@@@', re.M)
    _re_honor_zero_rc       = re.compile(r'^@@@HONOR_ZERO_RETURN_CODE@@@', re.M)
    _re_step_clear          = re.compile(r'^@@@STEP_CLEAR@@@', re.M)
    _re_step_summary_clear  = re.compile(r'^@@@STEP_SUMMARY_CLEAR@@@', re.M)
    _re_step_text           = re.compile(r'^@@@STEP_TEXT@(?P<text>.*)@@@', re.M)
    _re_step_summary_step   = re.compile(r'^@@@STEP_SUMMARY_TEXT@(?P<text>.*)@@@', re.M)
    _re_build_step          = re.compile(r'^@@@BUILD_STEP (?P<name>.*)@@@', re.M)

    _re_set = [
        # Support: @@@STEP_LINK@<name>@<url>@@@ (emit link)
        # Also support depreceated @@@link@<name>@<url>@@@
        ( STEP_LINK,            _re_step_link),

        # Support: @@@STEP_WARNINGS@@@ (warn on a stage)
        # Also support deprecated @@@BUILD_WARNINGS@@@
        ( STEP_WARNINGS,        _re_step_warnings ),

        # Support: @@@STEP_FAILURE@@@ (fail a stage)
        # Also support deprecated @@@BUILD_FAILED@@@
        ( STEP_FAILURE,         _re_step_failure ),

        # Support: @@@STEP_EXCEPTION@@@ (exception on a stage)
        # Also support deprecated @@@BUILD_FAILED@@@
        ( STEP_EXCEPTION,       _re_step_exception ),

        # Support: @@@HALT_ON_FAILURE@@@ (halt if a step fails immediately)
        ( HALT_ON_FAILURE,      _re_halt_on_failure ),

        # Support: @@@HONOR_ZERO_RETURN_CODE@@@ (succeed on 0 return, even if some
        # steps have failed)
        ( HONOR_ZERO_RC,        _re_honor_zero_rc ),

        # Support: @@@STEP_CLEAR@@@ (reset step description)
        ( STEP_CLEAR,           _re_step_clear ),

        # Support: @@@STEP_SUMMARY_CLEAR@@@ (reset step summary)
        ( STEP_SUMMARY_CLEAR,   _re_step_summary_clear ),

        # Support: @@@STEP_TEXT@<msg>@@@
        ( STEP_TEXT,            _re_step_text ),

        # Support: @@@STEP_SUMMARY_TEXT@<msg>@@@
        ( STEP_SUMMARY_TEXT,    _re_step_summary_step ),

        # Support: @@@BUILD_STEP <step_name>@@@ (start a new section)
        ( BUILD_STEP,           _re_build_step ),
    ]

    def __init__(self, **kwargs):
        # Inject standard tags into the environment.
        env = {
            'BUILDBOT_BLAMELIST':       util.Interpolate('%(prop:blamelist:-[])s'),
            'BUILDBOT_BRANCH':          util.Interpolate('%(prop:branch:-None)s'),
            'BUILDBOT_BUILDERNAME':     util.Interpolate('%(prop:buildername:-None)s'),
            'BUILDBOT_BUILDNUMBER':     util.Interpolate('%(prop:buildnumber:-None)s'),
            'BUILDBOT_CLOBBER':         util.Interpolate('%(prop:clobber:+1)s'),
            'BUILDBOT_GOT_REVISION':    util.Interpolate('%(prop:got_revision:-None)s'),
            'BUILDBOT_REVISION':        util.Interpolate('%(prop:revision:-None)s'),
            'BUILDBOT_SCHEDULER':       util.Interpolate('%(prop:scheduler:-None)s'),
            'BUILDBOT_SLAVENAME':       util.Interpolate('%(prop:slavename:-None)s'),
            'BUILDBOT_MSAN_ORIGINS':    util.Interpolate('%(prop:msan_origins:-)s'),
        }
        # Apply the passed in environment on top.
        old_env = kwargs.get('env') or {}
        env.update(old_env)
        # Change passed in args (ok as a copy is made internally).
        kwargs['env'] = env

        kwargs = self.setupShellMixin(kwargs)
        super().__init__(**kwargs)

        self.addLogObserver('stdio', logobserver.LineConsumerLogObserver(self.processAnnotations))
        # A step log to store all logs, which we got before the first @@@BUILD_STEP @@@ command.
        self.preamble_log = None

        self.annotate_status = results.SUCCESS
        self.halt_on_failure = False
        self.honor_zero_return_code = False

        self.annotated_steps = []
        # Use this lock to "run" the annotated steps.
        self.initLock = defer.DeferredLock()
        self._annotated_finished = False

    def _getLastAnnotatedStep(self):
        return self.annotated_steps[-1] if self.annotated_steps else None

    def _updateLastAnnotatedStepStatus(self, status):
        debuglog(">>> AnnotatedCommand::_updateLastAnnotatedStepStatus(%r)" % status)

        # Alway update the common annotate command status.
        self.annotate_status = results.worst_status(self.annotate_status, status)

        s = self._getLastAnnotatedStep()
        if s is not None:
            s.updateStatus(status)

        if self.halt_on_failure and status in [results.FAILURE, results.EXCEPTION]:
            if self.cmd:
                self.cmd.interrupt("Failed annotated step")

    def _updateLastAnnotatedStepText(self, text = None):
        """Updating a step text. None to clean up."""
        debuglog(">>> AnnotatedCommand::_updateLastAnnotatedStepText('%s')" % (text if text else ''))

        s = self._getLastAnnotatedStep()
        if s is not None:
            s.setStepText(text)

    def _updateLastAnnotatedStepSummaryInfo(self, text = None):
        """Updating a step summary info. None to clean up."""
        debuglog(">>> AnnotatedCommand::_updateLastAnnotatedStepSummaryInfo('%s')" % (text if text else ''))

        s = self._getLastAnnotatedStep()
        if s is not None:
            s.setStepSummary(text)

    def _fixupActiveAnnotatedStep(self):
        debuglog(">>> AnnotatedCommand::_fixupActiveAnnotatedStep()")
        # Fixup the active step
        s = self._getLastAnnotatedStep()
        if s is not None:
            # Finish the active step with its current status.
            s.requestFinish()

    def _scheduleNewAnnotatedStep(self, name, logline):
        debuglog(">>> AnnotatedCommand::_scheduleNewAnnotatedStep('%s')" % name)

        self._fixupActiveAnnotatedStep()

        s = AnnotatedBuildStep(parent_step=self, name=name)
        # Doing this last so that @@@BUILD_STEP... occurs in the log of the new
        # step.
        s.scheduleStdout(logline)
        # Make it ready to consume the logs and status updates.
        self.annotated_steps.append(s)


    @deferredLocked("initLock")
    @defer.inlineCallbacks
    def _execStep(self, step):
        yield step.startStep(remote=None)

    @defer.inlineCallbacks
    def _walkOverScheduledAnnotatedSteps(self):
        debuglog(">>> AnnotatedCommand::_walkOverScheduledAnnotatedSteps: started")

        while self.annotated_steps or not self._annotated_finished:
            if self.annotated_steps:
                if self._annotated_finished:
                    # Reset a status for all unprocessed annotated steps to
                    # the common annotate status.
                    self.annotated_steps[0].updateStatus(self.annotate_status)
                yield self._execStep(self.annotated_steps[0])
                last_step = self.annotated_steps.pop(0)
                if last_step.results == results.EXCEPTION:
                    raise Exception("Annotated step exception")

            yield asyncSleep(.1)

        debuglog(">>> AnnotatedCommand::_walkOverScheduledAnnotatedSteps: finished")

    def run(self):
        return self.runAnnotatedCommands()

    @defer.inlineCallbacks
    def runAnnotatedCommands(self):
        try:
            # Create a preamble log for primary annotate step.
            self.preamble_log = yield self.addLog('preamble')

            cmd = yield self.makeRemoteShellCommand(command=self.command,
                                                    stdioLogName='stdio')

            d1 = self.runCommand(cmd)
            d2 = defer.maybeDeferred(self._walkOverScheduledAnnotatedSteps)

            @d1.addBoth
            def cb(r):
                self._annotated_finished = True
                try:
                    # In some cases we can get the empty queue after the check.
                    # Just catch and pass the exception.
                    if self.annotated_steps:
                        # Current processing step.
                        last_step = self.annotated_steps[0]
                        cmd_results = cmd.results()
                        # We can get CANCELLED for two cases:
                        # 1. when UI stop button was pressed. In that case just pass this status
                        #    into the annotated step as the result status.
                        # 2. and when the remote command was canceled because of failed annotated step.
                        #    For that situation we finish the annotated step with its current status.
                        if cmd_results == results.CANCELLED and last_step.results in [results.FAILURE, results.EXCEPTION]:
                            # Finish the annotated step with its current status.
                            last_step.requestFinish()
                        else:
                            last_step.requestFinish(cmd_results)
                except IndexError:
                    pass
                return r

            @d2.addErrback
            def cbErrback(r):
                debuglog("+++ AnnotatedCommand::runAnnotatedCommands(): error callback with exception. "
                         "Terminate remote command.")
                self.annotate_status = results.EXCEPTION
                if self.cmd:
                    self.cmd.interrupt("Annotated step exception")
                return r

            # Wait until both -- the remote command and the annotated step processing loop -- get finished.
            yield defer.DeferredList([d1, d2])

        except Exception:
            why = failure.Failure()
            logging.err(why, "AnnotatedCommand.failed; traceback follows")
            yield self.addLogWithFailure(why)

        # This case when the remote command has been canceled by failed annotated command.
        if cmd.results() == results.CANCELLED and self.annotate_status in [results.FAILURE, results.EXCEPTION]:
            return self.annotate_status
        # Regular case.
        return results.worst_status(cmd.results(), self.annotate_status)

    def processAnnotations(self):

        while True:
            try:
                stream, ln = yield
                # Add \n if not there, which seems to be the case for log lines from
                # windows agents, but not others.
                if not ln.endswith('\n'):
                    ln += '\n'

                self.processAnnotatedCommand(ln)
            except GeneratorExit:
                # Done with log, the last active annotated step should get everything we got.
                # Just stop it and let the "main" step get completed.
                self._fixupActiveAnnotatedStep()
                return

    def processAnnotatedCommand(self, line):
        #pylint: disable=too-many-branches

        # returns: op, args
        def parse_annotate_cmd(ln):
            for ancmd, anre in AnnotatedCommand._re_set:
                ro = anre.search(ln)
                if ro is not None:
                    # Get the regex named group values.
                    # We can get the empty set, but it is ok.
                    args = ro.groupdict() or {}
                    # Store the current log line within the arguments.
                    # We will need to save it in some cases.
                    args['logline'] = ln
                    return ancmd, args
            return None, None

        ancmd, args = parse_annotate_cmd(line)

        if ancmd:
            debuglog(">>> AnnotatedCommand::processAnnotatedCommand(): %s, %r" % (ancmd, args))

        try:
            if ancmd == STEP_LINK:
                s = self._getLastAnnotatedStep()
                if s is not None:
                    s.addURL(args['link_label'], args['link_url'])
                else:
                    logging.msg("Warning: missed link for annotated step. "
                                "No active steps. (%s/%s)" % (args['link_label'], args['link_url']))

            elif ancmd == STEP_WARNINGS:
                self._updateLastAnnotatedStepStatus(results.WARNINGS)
            elif ancmd == STEP_FAILURE:
                self._updateLastAnnotatedStepStatus(results.FAILURE)
            elif ancmd == STEP_EXCEPTION:
                self._updateLastAnnotatedStepStatus(results.EXCEPTION)
            elif ancmd == HALT_ON_FAILURE:
                self.halt_on_failure = True
            elif ancmd == HONOR_ZERO_RC:
                self.honor_zero_return_code = True
            elif ancmd == STEP_CLEAR:
                self._updateLastAnnotatedStepText()
            elif ancmd == STEP_SUMMARY_CLEAR:
                self._updateLastAnnotatedStepSummaryInfo()
            elif ancmd == STEP_TEXT:
                self._updateLastAnnotatedStepText(text=args['text'])
            elif ancmd == STEP_SUMMARY_TEXT:
                self._updateLastAnnotatedStepSummaryInfo(text=args['text'])
            elif ancmd == BUILD_STEP:
                self._scheduleNewAnnotatedStep(name=args['name'].strip(),
                                               logline=args['logline'])
            else:
                # Regular log line, forward it to the active step.
                s = self._getLastAnnotatedStep()
                if s is None and self.preamble_log is not None:
                    self.preamble_log.addStdout(line)
                else:
                    s.scheduleStdout(line)

        except Exception:
            logging.err(failure.Failure(), 'error while processing annotgated command log:')
