"""
Module to provide for an encapsulation of the image element.
"""

import logging
from typing import Dict, List, Optional, cast

from pymarkdown.general.parser_helper import ParserHelper
from pymarkdown.general.parser_logger import ParserLogger
from pymarkdown.links.link_helper_properties import LinkHelperProperties
from pymarkdown.tokens.html_items import HtmlItems, HtmlOpenCloseTagItem
from pymarkdown.tokens.link_start_markdown_token import LinkStartMarkdownToken
from pymarkdown.tokens.markdown_token import MarkdownToken
from pymarkdown.tokens.reference_markdown_token import ReferenceMarkdownToken
from pymarkdown.transform_gfm.transform_state import TransformState
from pymarkdown.transform_markdown.markdown_transform_context import (
    MarkdownTransformContext,
    RegisterHtmlTransformHandlersProtocol,
    RegisterMarkdownTransformHandlersProtocol,
)

POGGER = ParserLogger(logging.getLogger(__name__))


class ImageStartMarkdownToken(ReferenceMarkdownToken):
    """
    Class to provide for an encapsulation of the image element.
    """

    # pylint: disable=too-many-arguments
    def __init__(
        self,
        image_alt_text: str,
        text_from_blocks: str,
        line_number: int,
        column_number: int,
        lhp: LinkHelperProperties,
    ) -> None:
        """
        Initialize an instance of the ImageStartMarkdownToken class.
        """
        self.__image_alt_text = image_alt_text
        ReferenceMarkdownToken.__init__(
            self,
            lhp,
            ImageStartMarkdownToken.get_markdown_token_type(),
            self.__image_alt_text,
            text_from_blocks,
            line_number=line_number,
            column_number=column_number,
        )

    # pylint: enable=too-many-arguments

    # pylint: disable=protected-access
    @staticmethod
    def get_markdown_token_type() -> str:
        """
        Get the type of markdown token for rehydration purposes.
        """
        return MarkdownToken._token_inline_image

    # pylint: enable=protected-access

    @property
    def image_alt_text(self) -> str:
        """
        Returns the text extracted from the blocks of the link, after processing.
        """
        return self.__image_alt_text

    def register_for_markdown_transform(
        self, registration_function: RegisterMarkdownTransformHandlersProtocol
    ) -> None:
        """
        Register any rehydration handlers for leaf markdown tokens.
        """
        registration_function(
            ImageStartMarkdownToken,
            ImageStartMarkdownToken.__rehydrate_inline_image,
            None,
        )

    @staticmethod
    def __rehydrate_inline_image(
        context: MarkdownTransformContext,
        current_token: MarkdownToken,
        previous_token: Optional[MarkdownToken],
    ) -> str:
        """
        Rehydrate the image text from the token.
        """
        _ = previous_token

        if context.block_stack[-1].is_inline_link:
            return ""
        inline_current_token = cast(ImageStartMarkdownToken, current_token)
        POGGER.debug(
            f">>>>>>>>:{ParserHelper.make_value_visible(inline_current_token)}:<<<<<"
        )
        rehydrated_text = (
            ImageStartMarkdownToken.rehydrate_inline_image_text_from_token(
                inline_current_token
            )
        )
        POGGER.debug(
            f">>>>>>>>:{ParserHelper.make_value_visible(rehydrated_text)}:<<<<<"
        )
        return LinkStartMarkdownToken.insert_leading_whitespace_at_newlines(
            context, rehydrated_text
        )

    @staticmethod
    def rehydrate_inline_image_text_from_token(
        image_token: "ImageStartMarkdownToken",
    ) -> str:
        """
        Given an image token, rehydrate it's original text from the token.
        """
        return f"!{LinkStartMarkdownToken.rehydrate_inline_link_text_from_token(image_token)}"

    @staticmethod
    def register_for_html_transform(
        register_handlers: RegisterHtmlTransformHandlersProtocol,
    ) -> None:
        """
        Register any functions required to generate HTML from the tokens.
        """
        register_handlers(
            ImageStartMarkdownToken, ImageStartMarkdownToken.__handle_image_token, None
        )

    @classmethod
    def __handle_image_token(
        cls,
        output_html: str,
        output_parts: List[HtmlItems],
        next_token: MarkdownToken,
        transform_state: TransformState,
    ) -> str:
        _ = transform_state

        image_token = cast(ImageStartMarkdownToken, next_token)

        attributes_map: Dict[str, str] = {
            "src": image_token.link_uri,
            "alt": image_token.image_alt_text,
        }
        if image_token.link_title:
            attributes_map["title"] = image_token.link_title

        output_parts.append(HtmlOpenCloseTagItem("img", attributes_map))

        return cls.__handle_image_token_old(output_html, image_token)

    @classmethod
    def __handle_image_token_old(
        cls, output_html: str, image_token: "ImageStartMarkdownToken"
    ) -> str:
        token_parts = [
            '<img src="',
            image_token.link_uri,
            '" alt="',
            image_token.image_alt_text,
            '" ',
            (f'title="{image_token.link_title}" ' if image_token.link_title else ""),
            "/>",
        ]
        token_parts.insert(0, output_html)
        return "".join(token_parts)
