"""
Support for updating the node information file for OmniGraph Nodes.

Exported Methods:
    generate_node_info
"""
import json
from json.decoder import JSONDecodeError
from typing import Optional

from .nodes import NodeInterfaceGenerator
from .utils import GeneratorConfiguration, ParseError, ensure_writable_directory, logger

__all__ = [
    "generate_node_info",
]


# ======================================================================
class NodeInfoGenerator(NodeInterfaceGenerator):
    """Manage the functions required to generate a C++ interface for a node"""

    def __init__(self, configuration: GeneratorConfiguration):
        """Set up the generator and output the meta-information for the node

        Just passes the initialization on to the parent class. See the argument and exception descriptions there.
        """
        logger.info("Creating NodeInfoGenerator")
        try:
            ensure_writable_directory(configuration.destination_directory)
        except Exception as error:
            raise ParseError("Unable to create node information directory") from error
        super().__init__(configuration)

        try:
            with open(self.output_path, "r", encoding="utf-8") as output_fd:
                self.node_information = json.load(output_fd)
        except (FileNotFoundError, KeyError, JSONDecodeError):
            self.node_information = {"nodes": {}}

    # ----------------------------------------------------------------------
    def interface_file_name(self) -> str:
        """Return the path to the name of the node information file, relative to the configured directory"""
        return "nodes.json"

    # ----------------------------------------------------------------------
    def generate_node_interface(self):
        """Generate the node information for the node"""
        logger.info("Generating node information for node %s", self.node_interface.name)
        this_nodes_information = {
            self.node_interface.name: {
                "description": self.node_interface.description,
                "version": self.node_interface.version,
                "extension": self.extension,
                "language": self.node_interface.language,
            }
        }
        self.node_information["nodes"].update(this_nodes_information)
        node_info_as_json = json.dumps(self.node_information, indent=4)
        self.out.write(node_info_as_json)


# ======================================================================
def generate_node_info(configuration: GeneratorConfiguration) -> Optional[str]:
    """Create or modify the extension's node information file

    Args:
        configuration: Information defining how and where the node information file will be generated

    Returns:
        String containing the generated/updated node information

    Raises:
        NodeGenerationError: When there is a failure in the generation of the node information file
    """
    logger.info("Generating node information")
    generator = NodeInfoGenerator(configuration)
    generator.generate_interface()

    return str(generator.out)
