# 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 subprocess
import sys
import threading
import time
import pty
import re

from dataclasses import dataclass


class LogPipe(threading.Thread):

    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
        if sys.platform == 'darwin':
            self.fd_read, self.fd_write = pty.openpty()
        else:
            self.fd_read, self.fd_write = os.pipe()

        self.pipeReader = os.fdopen(self.fd_read)
        self.captured_logs = []
        self.capture_delegate = capture_delegate
        self.name = name

        self.start()

    def CapturedLogContains(self, txt: str):
        return any(txt in l for l in 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."""
        for line in iter(self.pipeReader.readline, ''):
            logging.log(self.level, line.strip('\n'))
            self.captured_logs.append(line)
            if self.capture_delegate:
                self.capture_delegate.Log(self.name, line)

        self.pipeReader.close()

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


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

    def RunSubprocess(self, cmd, name, wait=True, dependencies=[]):
        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 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

        while s.poll() is None:
            # dependencies MUST NOT be done
            for dependency in dependencies:
                if dependency.poll() is not None:
                    s.kill()
                    raise Exception("Unexpected return %d for %r",
                                    dependency.poll(), dependency)

        code = s.wait()
        if code != 0:
            raise Exception('Command %r failed: %d' % (cmd, code))
        else:
            logging.debug('Command %r completed with error code 0', cmd)
