# Copyright (c) 2021 Project CHIP Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging
import os
import pty
import queue
import re
import subprocess
import sys
import threading
import typing


class LogPipe(threading.Thread):
    """Create PTY-based PIPE for IPC.

    Python provides a built-in mechanism for creating comunication PIPEs for
    subprocesses spawned with Popen(). However, created PIPEs will most likely
    enable IO buffering in the spawned process. In order to trick such process
    to flush its streams immediately, we are going to create a PIPE based on
    pseudoterminal (PTY).
    """

    def __init__(self, level, capture_delegate=None, name=None):
        """
        Setup the object with a logger and a loglevel and start the thread.
        """
        threading.Thread.__init__(self)

        self.daemon = False
        self.level = level
        self.fd_read, self.fd_write = pty.openpty()
        self.reader = open(self.fd_read, encoding='utf-8', errors='ignore')
        self.captured_logs = []
        self.capture_delegate = capture_delegate
        self.name = name

        self.start()

    def CapturedLogContains(self, txt: str, index=0):
        for i, line in enumerate(self.captured_logs[index:]):
            if txt in line:
                return True, i
        return False, len(self.captured_logs)

    def FindLastMatchingLine(self, matcher):
        for l in reversed(self.captured_logs):
            match = re.match(matcher, l)
            if match:
                return match
        return None

    def fileno(self):
        """Return the write file descriptor of the pipe."""
        return self.fd_write

    def run(self):
        """Run the thread, logging everything."""
        while True:
            try:
                line = self.reader.readline()
                # It seems that Darwin platform returns empty string in case
                # when writing side of PTY is closed (Linux raises OSError).
                if line == '':
                    break
            except OSError:
                break
            logging.log(self.level, line.strip('\n'))
            self.captured_logs.append(line)
            if self.capture_delegate:
                self.capture_delegate.Log(self.name, line)
        self.reader.close()

    def close(self):
        """Close the write end of the pipe."""
        os.close(self.fd_write)


class RunnerWaitQueue:
    def __init__(self, timeout_seconds: typing.Optional[int]):
        self.queue = queue.Queue()
        self.timeout_seconds = timeout_seconds
        self.timed_out = False

    def __wait(self, process, userdata):
        if userdata is None:
            # We're the main process for this wait queue.
            timeout = self.timeout_seconds
        else:
            timeout = None
        try:
            process.wait(timeout)
        except subprocess.TimeoutExpired:
            self.timed_out = True
            process.kill()
            # And wait for the kill() to kill it.
            process.wait()
        self.queue.put((process, userdata))

    def add_process(self, process, userdata=None):
        t = threading.Thread(target=self.__wait, args=(process, userdata))
        t.daemon = True
        t.start()

    def get(self):
        return self.queue.get()


class Runner:

    def __init__(self, capture_delegate=None):
        self.capture_delegate = capture_delegate

    def RunSubprocess(self, cmd, name, wait=True, dependencies=[], timeout_seconds: typing.Optional[int] = None):
        outpipe = LogPipe(
            logging.DEBUG, capture_delegate=self.capture_delegate,
            name=name + ' OUT')
        errpipe = LogPipe(
            logging.INFO, capture_delegate=self.capture_delegate,
            name=name + ' ERR')

        if sys.platform == 'darwin':
            # Try harder to avoid any stdout buffering in our tests
            cmd = ['stdbuf', '-o0'] + cmd

        if self.capture_delegate:
            self.capture_delegate.Log(name, 'EXECUTING %r' % cmd)

        s = subprocess.Popen(cmd, stdout=outpipe, stderr=errpipe)
        outpipe.close()
        errpipe.close()

        if not wait:
            return s, outpipe, errpipe

        wait = RunnerWaitQueue(timeout_seconds=timeout_seconds)
        wait.add_process(s)

        for dependency in dependencies:
            for accessory in dependency.accessories:
                wait.add_process(accessory, dependency)

        for process, userdata in iter(wait.queue.get, None):
            if process == s:
                break
            # dependencies MUST NOT be done
            s.kill()
            raise Exception("Unexpected return %d for %r" %
                            (process.returncode, userdata))

        if s.returncode != 0:
            if wait.timed_out:
                raise Exception("Command %r exceeded test timeout (%d seconds)" % (cmd, wait.timeout_seconds))
            else:
                raise Exception('Command %r failed: %d' % (cmd, s.returncode))

        logging.debug('Command %r completed with error code 0', cmd)
