import re

from . import icon


class Channels:
    LOWEST_CHAR_LIMIT = 91
    HIGHEST_CHAR_LIMIT = 166
    EXT_CHAR_LIMIT = 260

    def __init__(self, channels: list):
        self.channels = channels

    def length(self):
        return sum([len(_) for _ in self.channels]) + 2 * (len(self.channels) - 1)

    def truncate(self, highest_char_limit=HIGHEST_CHAR_LIMIT):
        while self.length() > highest_char_limit:
            self.channels.pop()


class GenerateTemplate:
    ICON_PATH = "images/server_icons"

    def __init__(
        self,
        name: str,
        invite_code: str,
        official: bool,
        homepage: str,
        git: str,
        notable_channels: list,
        language,
        icon_path=ICON_PATH,
    ):
        self.name = name
        self.invite_code = invite_code
        self.official = official
        self.homepage = homepage
        self.git = git
        self.channels = notable_channels
        self.language = language
        self.icon_path = icon_path

    def format_name(self):
        return f"{self.name}"

    def format_invite(self):
        return f"https://discord.com/invite/{self.invite_code}"

    def format_icon(self):
        if (
            self.icon_path is GenerateTemplate.ICON_PATH
        ):  # alternative: self.__init__.__defaults__[0]
            return (
                f'<img align="left" height="94px" width="94px" alt="Server Icon" src="{self.icon_path}/'
                f'{icon.GetIcon.icon_name(self.name)}.webp"> '
            )
        return f'<img align="left" height="94px" width="94px" alt="Server Icon" src="{self.icon_path}"> '

    def format_reddit(self):
        # From subreddit name rule: https://redd.it/592kmw
        m = (
            re.search(r"reddit.com/r/[a-zA-Z0-9_]+/?", self.homepage)
            if self.homepage
            else None
        )
        if m:
            return (
                ' [<img height="16px" width="16px" alt="Reddit Badge" src="images/badges/reddit.webp">]'
                "(badges.md#reddit-badge)"
            )
        return ""

    def format_official(self):
        if self.official:
            if (self.official and not self.homepage) and (
                self.official and not self.git
            ):
                raise ValueError(
                    "An official community must have a homepage or Git repository that claims its ownership"
                )
            return (
                ' [<img height="16px" width="16px" alt="Official Badge" src="images/badges/official.webp">]'
                "(badges.md#official-identification-badge)"
            )
        return ""

    def format_homepage(self):
        if self.homepage:
            return (
                f' [<img height="16px" width="16px" alt="Homepage URL" src="images/badges/homepage.webp">]'
                f"({self.homepage})"
            )
        return ""

    def format_git(self):
        if self.git:
            return f' [<img height="16px" width="16px" alt="Git Repository" src="images/badges/git.webp">]({self.git})'
        return ""

    def format_channels(self):
        channels = ["#" + _ for _ in self.channels]
        c = Channels(channels)
        initial_length = c.length()
        if initial_length >= c.EXT_CHAR_LIMIT:
            c.truncate(
                c.HIGHEST_CHAR_LIMIT - 15
            )  # 15 is for the length of " so much more"
            channels.append("__[`so much more`](badges.md#so-much-more)__")
        else:
            c.truncate()
        return ", ".join([f"`{_}`" for _ in channels])

    def format_language(self):
        languages = (
            ", ".join(self.language)
            if isinstance(self.language, list)
            else self.language
        )
        return languages

    def padding(self):
        channel_limit = (
            len(self.format_channels()) - self.format_channels().count("`")
            <= Channels.LOWEST_CHAR_LIMIT
        )
        language_limit = len(self.format_language()) <= Channels.LOWEST_CHAR_LIMIT
        return " \\\n<br>" if channel_limit and language_limit else ""
