# Copyright (C) 2025 Siemens
#
# SPDX-License-Identifier: MIT

from abc import abstractmethod
from enum import Enum
from pathlib import Path
from io import IOBase

from ..sbom import SBOMType


class GraphOutputFormat(Enum):
    """Enum of supported graph formats"""

    GRAPHML = (0,)

    @classmethod
    def from_str(cls, name: str) -> "GraphOutputFormat":
        if name.lower() == "graphml":
            return cls.GRAPHML
        raise RuntimeError(f"Unsupported output format: '{name}'")


class GraphExporter:
    """
    Base class of graph exporters
    """

    @staticmethod
    def create(filename: Path, format: GraphOutputFormat) -> "GraphExporter":
        """
        Factory to create a GraphExporter for the given SBOM type (based on the filename extension).
        """
        if filename.name.endswith("spdx.json"):
            SBOMType.SPDX.validate_dependency_availability()
            from ..bomreader.spdxbomreader import SpdxBomReader
            from .spdx import SpdxGraphMLExporter

            bom = SpdxBomReader.read_file(filename)
            if format == GraphOutputFormat.GRAPHML:
                return SpdxGraphMLExporter(bom)
        elif filename.name.endswith("cdx.json"):
            SBOMType.CycloneDX.validate_dependency_availability()
            from ..bomreader.cdxbomreader import CdxBomReader
            from .cdx import CdxGraphMLExporter

            bom = CdxBomReader.read_file(filename)
            if format == GraphOutputFormat.GRAPHML:
                return CdxGraphMLExporter(bom)
        else:
            raise RuntimeError("Cannot determine file format")

    @staticmethod
    def from_stream(
        stream: IOBase, bomtype: SBOMType, format: GraphOutputFormat
    ) -> "GraphExporter":
        """
        Factory to create a GraphExporter for the given SBOM type that takes the SBOM as stream.
        """
        bomtype.validate_dependency_availability()
        if bomtype == SBOMType.SPDX:
            from ..bomreader.spdxbomreader import SpdxBomReader
            from .spdx import SpdxGraphMLExporter

            bom = SpdxBomReader.read_stream(stream)
            if format == GraphOutputFormat.GRAPHML:
                return SpdxGraphMLExporter(bom)
        else:
            from ..bomreader.cdxbomreader import CdxBomReader
            from .cdx import CdxGraphMLExporter

            bom = CdxBomReader.read_stream(stream)
            if format == GraphOutputFormat.GRAPHML:
                return CdxGraphMLExporter(bom)

    @abstractmethod
    def export(self, output: IOBase):
        """Export the graph. Abstract method."""
        raise NotImplementedError()
