from hashlib import sha3_256
import colorsys


templates = {}

templates['Section_Begin'] = '<uu5string/><UU5.Bricks.Lsi><UU5.Bricks.Lsi.Item language="%language_code%">'
templates['TSDefinition_Begin'] = '<div id="%TSDefinitionCode%"><UU5.Bricks.Link href="#%TSDefinitionCode%" target="_self"><UU5.Bricks.Icon icon="mdi-blank"/></UU5.Bricks.Link></div>'
templates['TSDefinition_Block'] = '<Uu5Bricks.Block baseUri="https://www.plus4u.net" headerSeparator footerSeparator id="0" info="TSDefinition" ' \
'style="borderColor: %border_color%;" footer="<uu5string/><span style=~"<uu5json/>{~~~"color~~~": ~~~"rgb(158, 158, 158)~~~"}~">%footer%</span>" ' \
'margin=0 contentPadding="0 b" header="%TSDefinitionCode%" collapsible>'
templates['TSDefinition_BlockSectionStart'] = '<Uu5Bricks.Section headerSeparator=false contentPadding="0 b">'
templates['TSDefinition_BlockContent'] = '<UU5.RichText.Block uu5string="<uu5string/>' \
'<strong>Name:</strong> %name%' \
'<UU5.Bricks.Div><strong>Short Name:</strong> %short_name%</UU5.Bricks.Div>' \
'<UU5.Bricks.Div><strong>Description:</strong> %description%</UU5.Bricks.Div>' \
'<UU5.Bricks.Div><strong>Data Provider:</strong> %dataprovider%</UU5.Bricks.Div>'
templates['TSDefinition_BlockContentFormulaDifferentialCalculationYes'] = '<UU5.Bricks.Div><strong>Formula computed using differential calculation:</strong> ' \
'<UU5.Bricks.Span style=~"<uu5json/>{~~~"backgroundColor~~~": ~~~"#C8E6C9~~~"}~">Yes</UU5.Bricks.Span></UU5.Bricks.Div>'
templates['TSDefinition_BlockContentFormulaDifferentialCalculationNo'] = '<UU5.Bricks.Div><strong>Formula computed using differential calculation:</strong> ' \
'<UU5.Bricks.Span>No</UU5.Bricks.Span></UU5.Bricks.Div>'
templates['TSDefinition_BlockSectionEnd'] = '"/></Uu5Bricks.Section><Uu5Bricks.Section headerSeparator=false margin=0 contentPadding=0>'
templates['TSDefinition_Formula'] = '<Uu5CodeKitBricks.Code value="%formula%" codeStyle="javascript" maxRows=50 indent=4/>'
templates['TSDefinition_PredecessorsStart'] = '<Uu5Bricks.Layout type="columns"><Uu5Bricks.Layout.Item colSpan="m: 6">' \
'<UuContentKit.Bricks.BlockDefault icon="mdi-arrow-collapse-right">' \
'<UU5.RichText.Block uu5string="<uu5string/><UU5.Bricks.Div><UU5.Bricks.Span style=\\\"<uu5json/>{\\\\\\\"color\\\\\\\": \\\\\\\"#B71C1C\\\\\\\"' \
'}\\\"><strong>Predecessors (total %predecessors_count%):</strong></UU5.Bricks.Span></UU5.Bricks.Div><UU5.Bricks.Ul>'
templates['TSDefinition_Predecessor'] = '<UU5.Bricks.Li>' \
'<UU5.Bricks.Link href=~"%predecessor_link%~" target=~"_self~">%predecessor%</UU5.Bricks.Link></UU5.Bricks.Li>'
templates['TSDefinition_PredecessorsEnd'] = '</UU5.Bricks.Ul>"/></UuContentKit.Bricks.BlockDefault></Uu5Bricks.Layout.Item>'
templates['TSDefinition_SuccessorsStart'] = '<Uu5Bricks.Layout.Item colSpan="m: 6">' \
'<UuContentKit.Bricks.BlockDefault icon="mdi-arrow-expand-right">' \
'<UU5.RichText.Block uu5string="<uu5string/><UU5.Bricks.Div><UU5.Bricks.Span style=\\\"<uu5json/>{\\\\\\\"color\\\\\\\": \\\\\\\"#1B5E20\\\\\\\"' \
'}\\\"><strong>Successors (total %SuccessorsCount%):</strong></UU5.Bricks.Span></UU5.Bricks.Div><UU5.Bricks.Ul>'
templates['TSDefinition_Successor'] = '<UU5.Bricks.Li>' \
'<UU5.Bricks.Link href=~"%successor_link%~" target=~"_self~">%successor%</UU5.Bricks.Link></UU5.Bricks.Li>'
templates['TSDefinition_SuccessorsEnd'] = '</UU5.Bricks.Ul>"/></UuContentKit.Bricks.BlockDefault></Uu5Bricks.Layout.Item></Uu5Bricks.Layout>'
templates['TSDefinition_End'] = '</Uu5Bricks.Section></Uu5Bricks.Block>'
templates['Section_End'] = '</UU5.Bricks.Lsi.Item></UU5.Bricks.Lsi>'

templates['TSObjectType_Separator'] = '<br/><br/><UU5.Bricks.Line colorSchema="grey-rich" size="m"/>'
templates['TSObjectType_Begin'] = '<div id="%TSObjectTypeCode%"><UU5.Bricks.Link href="#%TSObjectTypeCode%" target="_self"><UU5.Bricks.Icon icon="mdi-blank"/></UU5.Bricks.Link></div>'
templates['TSObjectType_Block'] = '<Uu5Bricks.Block baseUri="https://www.plus4u.net" headerSeparator footerSeparator id="0" info="TSObjectType" ' \
'style="borderColor: %border_color%;" footer="<uu5string/><span style=~"<uu5json/>{~~~"color~~~": ~~~"rgb(158, 158, 158)~~~"}~">%footer%</span>" ' \
'margin=0 contentPadding="0 b" header="%TSObjectTypeCode%" collapsible significance="highlighted" colorScheme="%color_scheme%">'
templates['TSObjectType_BlockSectionStart'] = '<Uu5Bricks.Section headerSeparator=false contentPadding="0 b">'
templates['TSObjectType_BlockContent'] = '<UU5.RichText.Block uu5string="<uu5string/>' \
'<strong>Name:</strong> %name%' \
'<UU5.Bricks.Div><strong>Short Name:</strong> %short_name%</UU5.Bricks.Div>' \
'<UU5.Bricks.Div><strong>Description:</strong> %description%</UU5.Bricks.Div>' \
'<UU5.Bricks.Div><strong>TSDefinitions count:</strong> %tsdefinitions_count%</UU5.Bricks.Div>'
templates['TSObjectType_DimensionsBegin'] = '<UU5.Bricks.Div><strong>Dimensions (total %dimensions_count%):</strong></UU5.Bricks.Div><UU5.Bricks.Ul>'
templates['TSObjectType_Dimension'] = '<UU5.Bricks.Li>' \
'<UU5.Bricks.Link href=~"%dimension_link%~" target=~"_self~">%dimension%</UU5.Bricks.Link></UU5.Bricks.Li>'
templates['TSObjectType_DimensionsEnd'] = '</UU5.Bricks.Ul>'
templates['TSObjectType_BlockContentEnd'] = '"/>'
templates['TSObjectType_TransformationsToSectionStart'] = '<Uu5Bricks.Layout type="columns"><Uu5Bricks.Layout.Item colSpan="m: 6">' \
'<UuContentKit.Bricks.BlockDefault icon="mdi-arrow-collapse-right">' \
'<UU5.RichText.Block uu5string="<uu5string/><UU5.Bricks.Div><UU5.Bricks.Span style=\\\"<uu5json/>{\\\\\\\"color\\\\\\\": \\\\\\\"#B71C1C\\\\\\\"' \
'}\\\"><strong>Transformations to this TSObjectType (total %predecessors_count%):</strong></UU5.Bricks.Span></UU5.Bricks.Div><UU5.Bricks.Ul>'
templates['TSObjectType_TransformationsToStart'] = '<UU5.Bricks.Li>' \
'<UU5.Bricks.Link href=~"%predecessor_link%~" target=~"_self~">%transformation_code%</UU5.Bricks.Link></UU5.Bricks.Li>'
templates['TSObjectType_TransformationsToEnd'] = '</UU5.Bricks.Ul>"/></UuContentKit.Bricks.BlockDefault></Uu5Bricks.Layout.Item>'
templates['TSObjectType_TransformationsFromSectionStart'] = '<Uu5Bricks.Layout.Item colSpan="m: 6">' \
'<UuContentKit.Bricks.BlockDefault icon="mdi-arrow-expand-right">' \
'<UU5.RichText.Block uu5string="<uu5string/><UU5.Bricks.Div><UU5.Bricks.Span style=\\\"<uu5json/>{\\\\\\\"color\\\\\\\": \\\\\\\"#1B5E20\\\\\\\"' \
'}\\\"><strong>Transformations from this TSObjectType (total %successors_count%):</strong></UU5.Bricks.Span></UU5.Bricks.Div><UU5.Bricks.Ul>'
templates['TSObjectType_TransformationsFromStart'] = '<UU5.Bricks.Li>' \
'<UU5.Bricks.Link href=~"%successor_link%~" target=~"_self~">%transformation_code%</UU5.Bricks.Link></UU5.Bricks.Li>'
templates['TSObjectType_TransformationsFromEnd'] = '</UU5.Bricks.Ul>"/></UuContentKit.Bricks.BlockDefault></Uu5Bricks.Layout.Item></Uu5Bricks.Layout>'
templates['TSObjectType_End'] = '</Uu5Bricks.Section></Uu5Bricks.Block>'

templates['TSObjectTypeRelation_Separator'] = '<br/><br/><UU5.Bricks.Line colorSchema="grey-rich" size="m"/>'
templates['TSObjectTypeRelation_Begin'] = '<div id="%TSObjectTypeRelationCode%"><UU5.Bricks.Link href="#%TSObjectTypeRelationCode%" target="_self"><UU5.Bricks.Icon icon="mdi-blank"/></UU5.Bricks.Link></div>'
templates['TSObjectTypeRelation_Block'] = '<Uu5Bricks.Block baseUri="https://www.plus4u.net" headerSeparator footerSeparator id="0" info="TSObjectTypeRelation" ' \
'style="borderColor: %border_color%;" footer="<uu5string/><span style=~"<uu5json/>{~~~"color~~~": ~~~"rgb(158, 158, 158)~~~"}~">%footer%</span>" ' \
'margin=0 contentPadding="0 b" header="%TSObjectTypeRelationCode%" collapsible significance="distinct" colorScheme="%color_scheme%">'
templates['TSObjectTypeRelation_BlockSectionStart'] = '<Uu5Bricks.Section headerSeparator=false contentPadding="0 b">'
templates['TSObjectTypeRelation_BlockContent'] = '<UU5.RichText.Block uu5string="<uu5string/>' \
'<strong>Name:</strong> %name%' \
'<UU5.Bricks.Div><strong>Short Name:</strong> %short_name%</UU5.Bricks.Div>' \
'<UU5.Bricks.Div><strong>Description:</strong> %description%</UU5.Bricks.Div>' \
'<UU5.Bricks.Div><strong>Relation Type:</strong> %relation_type%</UU5.Bricks.Div>' \
'<UU5.Bricks.Div><strong>Source: </strong><UU5.Bricks.Link href=~"%source_tsobjecttype_link%~" target=~"_self~">%source_tsobjecttype%</UU5.Bricks.Link></UU5.Bricks.Div>' \
'<UU5.Bricks.Div><strong>Target: </strong><UU5.Bricks.Link href=~"%target_tsobjecttype_link%~" target=~"_self~">%target_tsobjecttype%</UU5.Bricks.Link></UU5.Bricks.Div>"/>'
templates['TSObjectTypeRelation_End'] = '</Uu5Bricks.Section></Uu5Bricks.Block>'


def escape_str(value: str, use_br_for_newlines: bool) -> str:
    """
    Escape special characters in a string for HTML display.
    """
    result = value
    result = result.replace("\\", "\\\\").replace('\"', '\\\"').replace('\'', '\\\'')
    if use_br_for_newlines:
        result = result.replace("\r", "").replace("\n", "<br/>")
    else:
        result = result.replace("\r", "")
    return result

def use_template(template_name: str, replacements: dict[str, str], language: str, use_br_for_newlines: bool = True) -> str:
    """
    Replace placeholders in the template with actual values from replacements dictionary.
    Placeholders are in the format %placeholder%.
    """
    result = templates[template_name]
    result = result.replace("~", "\\")
    for key, value in replacements.items():
        placeholder = f"%{key}%"
        if isinstance(value, str):
            new_value = escape_str(value, use_br_for_newlines)           
            result = result.replace(placeholder, new_value)
        elif isinstance(value, dict) and language in value:
            new_value = escape_str(value[language], use_br_for_newlines)
            result = result.replace(placeholder, new_value)
        elif value is None:
            result = result.replace(placeholder, "--")
        else:
            raise ValueError(f"Unsupported replacement type for key '{key}': {type(value)}")
    return result

class Palette:
    @staticmethod
    def get_palette() -> list[str]:
        """
        Return a predefined palette of colors.
        """
        return [
            "#008000", "#000080", "#808000", "#008080", "#800080",
            "#FF0000", "#00FF00", "#0000FF", "#FF5733", "#303030",
            "#FFFF00", "#00FFFF", "#FF00FF", "#808080", "#800000",
            "#E27D60", "#85DCB0", "#E8A87C", "#C38D9E", "#41B3A3",
            "#6B5B95", "#FF6F61", "#88B04B", "#F7CAC9", "#92A8D1"
        ]
    
    @staticmethod
    def get_color(value: str) -> str:
        """
        Get a consistent color from the palette based on the hash of the input value.
        """
        value_hash = sha3_256(value.encode('utf-8')).hexdigest()
        # palette = Palette.get_palette()
        # index = int(value_hash, 16) % len(palette)
        # return palette[index]
        index = int(value_hash, 16) % 1080
        hue = index / 1080.0
        lightness = 0.3 + (index % 3) * 0.2
        rgb = colorsys.hls_to_rgb(hue, lightness, 1.0)
        return f"#{int(rgb[0]*255):02X}{int(rgb[1]*255):02X}{int(rgb[2]*255):02X}"
