from pathlib import Path
from unittest import TestCase

import pyGHDL.libghdl as libghdl
from pyGHDL.libghdl import name_table, files_map, errorout_console
from pyGHDL.libghdl.vhdl import nodes, sem_lib


if __name__ == "__main__":
    print("ERROR: you called a testcase declaration file as an executable module.")
    print("Use: 'python -m unitest <testcase module>'")
    exit(1)


class Instantiate(TestCase):
    _root = Path(__file__).resolve().parent.parent
    _filename: Path = _root / "dom/examples/SimpleEntity.vhdl"

    @staticmethod
    def getIdentifier(node):
        """Return the Python string from node :obj:`node` identifier."""
        return name_table.Get_Name_Ptr(nodes.Get_Identifier(node))

    def test_InitializeGHDL(self) -> None:
        """Initialization: set options and then load libaries."""
        libghdl.initialize()

        # Print error messages on the console.
        errorout_console.Install_Handler()

        # Set options. This must be done before analyze_init()
        libghdl.set_option("--std=08")

        # Finish initialization. This will load the standard package.
        if libghdl.analyze_init_status() != 0:
            self.fail("libghdl initialization error")

        # Load the file
        file_id = name_table.Get_Identifier(str(self._filename))
        sfe = files_map.Read_Source_File(name_table.Null_Identifier, file_id)
        if sfe == files_map.No_Source_File_Entry:
            self.fail(f"Cannot read file '{self._filename}'")

        # Parse
        file = sem_lib.Load_File(sfe)

        # Display all design units
        designUnit = nodes.Get_First_Design_Unit(file)
        while designUnit != nodes.Null_Iir:
            libraryUnit = nodes.Get_Library_Unit(designUnit)

            if nodes.Get_Kind(libraryUnit) == nodes.Iir_Kind.Entity_Declaration:
                entityName = self.getIdentifier(libraryUnit)
                self.assertEqual(
                    "counter",
                    entityName,
                    f"expected entity name 'counter', got '{entityName}'",
                )

            elif nodes.Get_Kind(libraryUnit) == nodes.Iir_Kind.Architecture_Body:
                architectureName = self.getIdentifier(libraryUnit)
                self.assertEqual(
                    "rtl",
                    architectureName,
                    f"expected architecture name 'rtl', got '{architectureName}'"
                )

            else:
                self.fail("Unknown unit.")

            designUnit = nodes.Get_Chain(designUnit)
