#!/usr/bin/env python3
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

import difflib
import filecmp
import inspect
import logging
import os
import re
import shlex
import signal
import subprocess
import time


class Process:
    """Utility class used to spawn an interact with processs.s"""

    def __init__(self,
                 cmd,
                 logdir,
                 cwd=None,
                 startup_done_expect=None,
                 startup_timeout=None):
        """Creates Process instance.

        Args:
            cmd: Command line argument used to spawn process.
            logdir: Directory used to store STDOUT and STDERR output.
            cwd: Working directory used to spawn process.
            startup_done_expect: Pattern used to check at process startup time.
            startup_timeout: Timeout in seconds for |startup_done_expect| check.
        """
        if isinstance(cmd, str):
            self.cmd = shlex.split(cmd)
        else:
            self.cmd = cmd
        self.logdir = logdir
        self.cwd = cwd
        self.startup_done_expect = startup_done_expect
        self.startup_timeout = startup_timeout
        self.proc = None
        self.logger = logging.getLogger(__name__)

        self._f_stdout = None
        self._f_stderr = None
        self._f_stdout_r = None
        self._f_stderr_r = None

    def __del__(self):
        try:
            self.proc.kill()
            self._f_stdout.close()
            self._f_stderr.close()
            self._f_stdout_r.close()
            self._f_stderr_r.close()
        except:
            pass

    def run(self):
        """Start process with command line configured in constructor."""
        cmd_name = os.path.basename(self.cmd[0])

        # Enforce line-buffered STDOUT even when sending STDOUT/STDERR to file.
        # If applications don't fflush() STDOUT manually, STDOUT goes through
        # a 4kB buffer before we see any output, which prevents searching for
        # the string indicating a successful startup.
        # see discussion at http://www.pixelbeat.org/programming/stdio_buffering/
        cmd = ['stdbuf', '-oL'] + self.cmd
        self.logger.info("Running command " + ' '.join(cmd))

        logfile_stdout = os.path.join(self.logdir,
                                      "{}.stdout".format(cmd_name))
        logfile_stderr = os.path.join(self.logdir,
                                      "{}.stderr".format(cmd_name))
        self.logger.debug("Capturing STDOUT at " + logfile_stdout)
        self.logger.debug("Capturing STDERR at " + logfile_stderr)

        self._f_stdout = open(logfile_stdout, 'w')
        self._f_stderr = open(logfile_stderr, 'w')
        self.proc = subprocess.Popen(
            cmd,
            cwd=self.cwd,
            universal_newlines=True,
            bufsize=1,
            stdin=subprocess.PIPE,
            stdout=self._f_stdout,
            stderr=self._f_stderr)

        self._f_stdout_r = open(logfile_stdout, 'r')
        self._f_stderr_r = open(logfile_stderr, 'r')

        # no startup match pattern given => startup done!
        if self.startup_done_expect == None:
            return True

        # check if the string indicating a successful startup appears in the
        # the program output (STDOUT or STDERR)
        init_done = self._find_in_output(
            pattern=self.startup_done_expect, timeout=self.startup_timeout)

        if init_done == None:
            raise subprocess.TimeoutExpired

        self.logger.info("Startup sequence matched, startup done.")

        return True

    def terminate(self):
        """Terminates process started by run call."""
        if not self.proc:
            return
        self.proc.terminate()

    def send_ctrl_c(self):
        """Sends SIGINT to process started by run call."""
        if not self.proc:
            return
        self.proc.send_signal(signal.SIGINT)

    def expect(self, stdin_data=None, pattern=None, timeout=None):
        """Write send to STDIN and check if the output is as expected.

        Args:
            stdin_data: Data to send to STDIN.
            pattern: Pattern to search for after sending |stdin_data|.
            timeout: Timeout in seconds for |pattern| check.
        Returns:
            True if |pattern| found, False otherwise.
        """
        # We don't get STDOUT/STDERR from subprocess.communicate() as it's
        # redirected to file. We need to read the files instead.

        # XXX: races (false positives) can happen here if output is generated
        # before the input is sent to the process.
        if pattern == None:
            self._f_stdout_r.seek(0, 2)

        self.proc.stdin.write(stdin_data)
        self.proc.stdin.flush()

        if pattern == None:
            return True

        return self._find_in_output(pattern, timeout) != None

    def _find_in_output(self, pattern, timeout):
        """Read STDOUT and STDERR to find an expected pattern.

        Both streams are reset to the start of the stream before searching.
        pattern can be of two types:
        1. A regular expression (a re object). In this case, the pattern is
           matched against all lines and the result of re.match(pattern) is
           returned. Multi-line matches are not supported.
        2. A string. In this case pattern is compared to each line with
           startswith(), and the full matching line is returned on a match.
        If no match is found None is returned.
        timeout is given in seconds.

        Args:
            pattern: Pattern to search for in STDOUT or STDERR.
            timeout: Timeout in seconds for |pattern| check.
        Returns:
            String containing |pattern|, None otherwise.
        """

        if timeout != None:
            t_end = time.time() + timeout


        # reset streams
        self._f_stdout_r.seek(0)
        self._f_stderr_r.seek(0)

        while True:
            # check STDOUT as long as there is one
            i = 0
            for line in self._f_stdout_r:
                i += 1
                if hasattr(pattern, "match"):
                    m = pattern.match(line)
                    if m:
                        return m
                else:
                    if line.startswith(pattern):
                        return line

                # Check if we exceed the timeout while reading from STDOUT
                # do so only every 100 lines to reduce the performance impact.
                if timeout != None and i % 100 == 99 and time.time() >= t_end:
                    break

            # check STDERR as long as there is one
            i = 0
            for line in self._f_stderr_r:
                i += 1
                if hasattr(pattern, "match"):
                    m = pattern.match(line)
                    if m:
                        return m
                else:
                    if line.startswith(pattern):
                        return line

                # Check if we exceed the timeout while reading from STDERR
                # do so only every 100 lines to reduce the performance impact.
                if timeout != None and i % 100 == 99 and time.time() >= t_end:
                    break

            # wait for 200ms for new output
            if timeout != None:
                try:
                    self.proc.wait(timeout=0.2)
                except subprocess.TimeoutExpired:
                    pass

        return None
