import unittest
import sys
import os

from utils import execute, kill, run_file, run_barebone

class TestConstructorsActionLanguage(unittest.TestCase):
    def test_constructors_simple(self):
        commands = ["output",                    # Output
                        "const", True,
                        True,                     # (has next)
                        "return",                # Return
                            True,                 # (has value)
                            "const", True,
                ]
        self.assertTrue(run_barebone(commands, [True], 1))

    def test_constructors_if_else_true(self):
        commands = ["if",                    # If
                        "const", True,    # Condition
                        "output",            # True-part
                            "const", True,
                            False,            # Has next
                        True,                 # Has else
                        "output",            # False-part
                            "const", False,
                            False,            # Has next
                        True,                 # Has next
                        "return",            # Return
                            True,             # Has value
                            "const", "true",
                ]
        self.assertTrue(run_barebone(commands, [True], 1))

    def test_constructors_if_else_false(self):
        commands = ["if",                    # If
                        "const", False,   # Condition
                        "output",            # True-part
                            "const", True,
                            False,            # Has next
                        True,                 # Has else
                        "output",            # False-part
                            "const", False,
                            False,            # Has next
                        True,                 # Has next
                        "return",            # Return
                            True,             # Has value
                            "const", "true",
                ]
        self.assertTrue(run_barebone(commands, [False], 1))

    def test_constructors_if_true(self):
        commands = ["if",                    # If
                        "const", True,    # Condition
                        "output",            # True-part
                            "const", True,
                            False,            # Has next
                        False,                # Has else
                        True,                 # Has next
                        "return",            # Return
                            True,             # Has value
                            "const", "true",
                ]
        self.assertTrue(run_barebone(commands, [True], 1))

    def test_constructors_if_false(self):
        commands = ["if",                    # If
                        "const", False,   # Condition
                        "output",            # True-part
                            "const", True,
                            False,            # Has next
                        False,                # Has else
                        True,                 # Has next
                        "return",            # Return
                            True,             # Has value
                            "const", "true",
                ]
        self.assertTrue(run_barebone(commands, [None], 1, timeout=True))

    def test_constructors_addition(self):
        commands = ["output",
                        "call",
                            "deref", "primitives/integer_addition",
                            2,
                            "const", 1,
                            "const", 5,
                            False,
                        True,
                        "return", True, "const", True,
                ]
        self.assertTrue(run_barebone(commands, [6], 1))

    def test_constructors_while_false(self):
        commands = ["while",                 # While
                        "const", False,   # Condition
                        "output",            # True-part
                            "const", True,
                            False,            # Has next
                        True,                 # Has next
                        "output",            # Output false
                            "const", False,
                            True,             # Has next
                            "return",        # Return
                                True,         # Has value
                                "const", "true",
                ]
        self.assertTrue(run_barebone(commands, [False], 1))

    def test_constructors_while_true(self):
        commands = ["while",                 # While
                        "const", True,    # Condition
                        "output",            # True-part
                            "const", True,
                            False,            # Has next
                        True,                 # Has next
                        "output",            # False-part
                            "const", False,
                            True,            # Has next
                        "return",            # Return
                            True,             # Has value
                            "const", "true",
                ]
        self.assertTrue(run_barebone(commands, [True, True, True, True], 1))

    def test_constructors_declare_and_assign(self):
        commands = ["declare",
                        "1",
                        True,
                    "assign",
                        "resolve", "1",
                        "const", 5,
                        True,
                    "output",
                        "access", "resolve", "1",
                        True,
                    "return",
                        True,
                        "const", "true",
                ]
        self.assertTrue(run_barebone(commands, [5], 1))

    def test_constructors_output_input(self):
        commands = ["output",
                        "input",
                        True,
                    "return",
                        True,
                        "const", "true",
                ]
        self.assertTrue(run_barebone(commands + [123456], [123456], 1))

    def test_constructors_continue(self):
        commands = ["while",
                        "const", True,
                        "output", "const", 1,
                            True,
                            "if",
                                "const", True,
                                "continue",
                                False,
                                True,
                            "output", "const", 2,
                                False,
                        True,
                    "output", "const", 3,
                        True,
                    "return", True,
                        "const", True,
                ]
        self.assertTrue(run_barebone(commands, [1, 1, 1, 1, 1], 1))

    def test_constructors_break(self):
        commands = ["while",
                        "const", True,
                        "output", "const", 1,
                            True,
                            "if",
                                "const", True,
                                "break",
                                False,
                                True,
                            "output", "const", 2,
                                False,
                        True,
                    "output", "const", 3,
                        True,
                    "return", True,
                        "const", True,
                ]
        self.assertTrue(run_barebone(commands, [1, 3], 1))
