from telethon.tl.types import (
    MessageEntityBlockquote,
    MessageEntityCustomEmoji,
    MessageEntityMention,
    MessageEntityMentionName,
    MessageEntitySpoiler,
    MessageEntityTextUrl,
)

from .patterns import PATTERNS


class EntitiesManager:
    async def parse(self, text: str):
        matches = []

        for name, pattern in PATTERNS.items():
            for match in pattern.finditer(text):
                matches.append({"name": name, "match": match})

        matches.sort(key=lambda x: x["match"].start())

        clean_text = text
        entities = []
        offset = 0

        for item in matches:
            name = item["name"]
            match = item["match"]
            start = match.start() - offset

            entity = None

            if name == "emoji":
                replacement = match.group(2)
                entity = MessageEntityCustomEmoji(
                    offset=start,
                    length=len(replacement),
                    document_id=int(match.group(1)),
                )
            elif name == "mention":
                user_id = match.group(1)
                replacement = match.group(2)
                entity = MessageEntityMentionName(
                    offset=start, length=len(replacement), user_id=int(user_id)
                )
            elif name == "link":
                url = match.group(1)
                replacement = match.group(2)
                entity = MessageEntityTextUrl(
                    offset=start, length=len(replacement), url=url or replacement
                )
            elif name == "spoiler":
                replacement = match.group(1)
                entity = MessageEntitySpoiler(offset=start, length=len(replacement))
            elif name == "blockquote":
                replacement = match.group(1)
                entity = MessageEntityBlockquote(
                    offset=start,
                    length=len(replacement),
                    collapsed="hide" in match.group(0),
                )

            if entity:
                entities.append(entity)

            clean_text = (
                clean_text[:start] + replacement + clean_text[match.end() - offset :]
            )
            offset += match.end() - match.start() - len(replacement)

        return clean_text, entities

    async def remove(self, text: str):
        clean_text, _ = await self.parse(text)
        return clean_text
