"""
Test Lua API wrapper
"""

from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
import subprocess


def to_string(b):
    """Return the parameter as type 'str', possibly encoding it.

    In Python2, the 'str' type is the same as 'bytes'. In Python3, the
    'str' type is (essentially) Python2's 'unicode' type, and 'bytes' is
    distinct.

    """
    if isinstance(b, str):
        # In Python2, this branch is taken for types 'str' and 'bytes'.
        # In Python3, this branch is taken only for 'str'.
        return b
    if isinstance(b, bytes):
        # In Python2, this branch is never taken ('bytes' is handled as 'str').
        # In Python3, this is true only for 'bytes'.
        try:
            return b.decode("utf-8")
        except UnicodeDecodeError:
            # If the value is not valid Unicode, return the default
            # repr-line encoding.
            return str(b)

    # By this point, here's what we *don't* have:
    #
    #  - In Python2:
    #    - 'str' or 'bytes' (1st branch above)
    #  - In Python3:
    #    - 'str' (1st branch above)
    #    - 'bytes' (2nd branch above)
    #
    # The last type we might expect is the Python2 'unicode' type. There is no
    # 'unicode' type in Python3 (all the Python3 cases were already handled). In
    # order to get a 'str' object, we need to encode the 'unicode' object.
    try:
        return b.encode("utf-8")
    except AttributeError:
        raise TypeError("not sure how to convert %s to %s" % (type(b), str))


class ExecuteCommandTimeoutException(Exception):
    def __init__(self, msg, out, err, exitCode):
        assert isinstance(msg, str)
        assert isinstance(out, str)
        assert isinstance(err, str)
        assert isinstance(exitCode, int)
        self.msg = msg
        self.out = out
        self.err = err
        self.exitCode = exitCode


# Close extra file handles on UNIX (on Windows this cannot be done while
# also redirecting input).
kUseCloseFDs = not (platform.system() == "Windows")


def executeCommand(command, cwd=None, env=None, input=None, timeout=0):
    """Execute command ``command`` (list of arguments or string) with.

    * working directory ``cwd`` (str), use None to use the current
    working directory
    * environment ``env`` (dict), use None for none
    * Input to the command ``input`` (str), use string to pass
    no input.
    * Max execution time ``timeout`` (int) seconds. Use 0 for no timeout.

    Returns a tuple (out, err, exitCode) where
    * ``out`` (str) is the standard output of running the command
    * ``err`` (str) is the standard error of running the command
    * ``exitCode`` (int) is the exitCode of running the command

    If the timeout is hit an ``ExecuteCommandTimeoutException``
    is raised.

    """
    if input is not None:
        input = to_bytes(input)
    p = subprocess.Popen(
        command,
        cwd=cwd,
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        env=env,
        close_fds=kUseCloseFDs,
    )
    timerObject = None
    # FIXME: Because of the way nested function scopes work in Python 2.x we
    # need to use a reference to a mutable object rather than a plain
    # bool. In Python 3 we could use the "nonlocal" keyword but we need
    # to support Python 2 as well.
    hitTimeOut = [False]
    try:
        if timeout > 0:

            def killProcess():
                # We may be invoking a shell so we need to kill the
                # process and all its children.
                hitTimeOut[0] = True
                killProcessAndChildren(p.pid)

            timerObject = threading.Timer(timeout, killProcess)
            timerObject.start()

        out, err = p.communicate(input=input)
        exitCode = p.wait()
    finally:
        if timerObject is not None:
            timerObject.cancel()

    # Ensure the resulting output is always of string type.
    out = to_string(out)
    err = to_string(err)

    if hitTimeOut[0]:
        raise ExecuteCommandTimeoutException(
            msg="Reached timeout of {} seconds".format(timeout),
            out=out,
            err=err,
            exitCode=exitCode,
        )

    # Detect Ctrl-C in subprocess.
    if exitCode == -signal.SIGINT:
        raise KeyboardInterrupt

    return out, err, exitCode


class TestLuaAPI(TestBase):
    NO_DEBUG_INFO_TESTCASE = True

    def get_tests(self):
        tests = []
        for filename in os.listdir():
            # Ignore dot files and excluded tests.
            if filename.startswith("."):
                continue

            # Ignore files that don't start with 'Test'.
            if not filename.startswith("Test"):
                continue

            if not os.path.isdir(filename):
                base, ext = os.path.splitext(filename)
                if ext == ".lua":
                    tests.append(filename)
        return tests

    def test_lua_api(self):
        if "LUA_EXECUTABLE" not in os.environ or not os.path.exists(
            os.environ["LUA_EXECUTABLE"]
        ):
            self.skipTest("Lua API tests could not find Lua executable.")
            return
        lua_executable = os.environ["LUA_EXECUTABLE"]
        lldb_lua_cpath = os.environ["LLDB_LUA_CPATH"]

        self.build()
        test_exe = self.getBuildArtifact("a.out")
        test_output = self.getBuildArtifact("output")
        test_input = self.getBuildArtifact("input")

        lua_prelude = "package.cpath = '%s/?.so;' .. package.cpath" % lldb_lua_cpath

        lua_env = {
            "TEST_EXE": os.path.join(self.getBuildDir(), test_exe),
            "TEST_OUTPUT": os.path.join(self.getBuildDir(), test_output),
            "TEST_INPUT": os.path.join(self.getBuildDir(), test_input),
        }

        for lua_test in self.get_tests():
            cmd = [lua_executable] + ["-e", lua_prelude] + [lua_test]
            out, err, exitCode = executeCommand(cmd, env=lua_env)

            # Redirect Lua output
            print(out)
            print(err, file=sys.stderr)

            self.assertEqual(exitCode, 0, "Lua test '%s' failure." % lua_test)
