from pathlib import Path
from .doctsobjecttyperelation import DocTsObjectTypeRelation
import fetchx.ioutils as ioutils
from .doctemplates import Palette, use_template


class DocDimension:
    def __init__(self, dimension_dict: dict, tsobjecttype: 'DocTsObjectType'):
        """
        Represents a Dimension of a Time Series Object Type in the metamodel.
        :param dimension_dict: Dictionary containing dimension properties.
        :param tsobjecttype: The parent DocTsObjectType instance.
        """
        super().__init__()
        self.alias = dimension_dict.get("alias", None)  # type: dict | None
        self.alias_code = self.alias.get("code", None) if self.alias else None
        self.tsObjectType_code = dimension_dict.get("tsObjectTypeCode", None)  # type: str | None
        self.tsObjectType = tsobjecttype  # type: DocTsObjectType | None

class DocTsObjectType(dict):
    def __init__(self, *args, **kwargs):
        """
        Represents a Time Series Object Type in the metamodel.
        Inherits from dict to store object type properties.
        """
        super().__init__(*args, **kwargs)
        self.dimensions = None  # type: list[DocDimension] | None
        self.tsdefinitions = []  # type: list['DocTsDefinition']
        self.relationsToThisTsObjectType = []  # type: list[DocTsObjectTypeRelation]
        self.relationsFromThisTsObjectType = []  # type: list[DocTsObjectTypeRelation]
        self._html = None  # type: str | None

    @property
    def color(self) -> str:
        """
        Get the color associated with this Time Series Object Type.
        :return: Color as a hex string.
        """
        return Palette.get_color(self.get("code", ""))

    @staticmethod
    def load_from_directory(base_path: Path) -> dict[str, 'DocTsObjectType']:
        """
        Load all Time Series Object Types from the specified directory.
        :param base_path: Base path where the metamodel is located.
        :return: A dictionary mapping object type codes to DocTsObjectType instances.
        """
        result = {}
        tsobjecttypes_path = base_path / "metamodel/tsObjectType"
        # Load all .json files
        files, directories = ioutils.search_folder(str(tsobjecttypes_path.resolve()), list_of_extensions=[".json"])
        for file in files:
            value = ioutils.load_json(file)
            code = Path(file).stem
            result[code] = DocTsObjectType(value)
        return result
    
    def to_string(self, language: str = "en") -> str:
        """
        Convert the Time Series Object Type to a string representation.
        :param language: Language code for localization.
        :return: String representation of the Time Series Object Type.
        """
        if self._html is not None:
            return self._html
        result = ""
        # generate tsobjecttype for specific language, e.g., 'en'
        result += use_template('TSObjectType_Begin', {'TSObjectTypeCode': self.get("code", "--")}, language=language)
        # Generate footer content
        footer_content = ""
        footer_content += f'<strong>Value Provider Type: </strong>{self.get("valueProviderType", "--")}, '
        footer_content += f'<strong>Value Provider API: </strong>{self.get("valueProviderApi", "--")}'
        # generate block with border color from parent tsobjecttype
        result += use_template('TSObjectType_Block',{
            'border_color': self.color,
            'footer': footer_content,
            'TSObjectTypeCode':self.get('code','--'),
            'color_scheme': 'building'
            }, language=language
        ) # type: ignore
        result += use_template('TSObjectType_BlockSectionStart', {}, language=language)
        # generate block content
        result += use_template('TSObjectType_BlockContent',{
            'name': self.get('name', '--'),
            'short_name': self.get('shortName', '--'),
            'description': self.get('desc', '--'),
            'tsdefinitions_count': str(len(self.tsdefinitions))
            }, language=language
        )
        # add dimensions
        if self.dimensions is not None and len(self.dimensions) > 0:
            result += use_template('TSObjectType_DimensionsBegin',{
                'dimensions_count': str(len(self.dimensions))
                }, language=language
            )
            # add each dimension
            for dimension in self.dimensions:
                dimension_code = dimension.tsObjectType_code if dimension.tsObjectType_code is not None else "--"
                dimension_alias = dimension.alias_code if dimension.alias_code is not None else "--"
                dimension_link = f'#{dimension_code}'
                dimension_name = dimension_code
                if dimension.alias_code is not None:
                    dimension_name += f' (alias: {dimension_alias})'
                result += use_template('TSObjectType_Dimension',{
                    'dimension_link': dimension_link,
                    'dimension': dimension_name
                    }, language=language
                )
            result += use_template('TSObjectType_DimensionsEnd', {}, language=language)
        result += use_template('TSObjectType_BlockContentEnd', {}, language=language)
        if len(self.relationsToThisTsObjectType) > 0 or len(self.relationsFromThisTsObjectType) > 0:
            # add predecessors section
            result += use_template('TSObjectType_TransformationsToSectionStart',{
                'predecessors_count': str(len(self.relationsToThisTsObjectType))
                }, language=language
            )
            for relation in self.relationsToThisTsObjectType:
                transformation_code = relation.get("code","--") # type: ignore
                predecessor_link = f'#{transformation_code}'
                result += use_template('TSObjectType_TransformationsToStart',{
                    'predecessor_link': predecessor_link,
                    'transformation_code': transformation_code
                    }, language=language
                )
            result += use_template('TSObjectType_TransformationsToEnd', {}, language=language)
            # add successors section
            result += use_template('TSObjectType_TransformationsFromSectionStart',{
                'successors_count': str(len(self.relationsFromThisTsObjectType))
                }, language=language
            )
            for relation in self.relationsFromThisTsObjectType:
                transformation_code = relation.get("code","--") # type: ignore
                successor_link = f'#{transformation_code}'
                result += use_template('TSObjectType_TransformationsFromStart',{
                    'successor_link': successor_link,
                    'transformation_code': transformation_code
                    }, language=language
                )
            result += use_template('TSObjectType_TransformationsFromEnd', {}, language=language)
        result += use_template('TSObjectType_End', {}, language=language)
        self._html = result
        return result
        