# Buggy code
def _format_pattern(self, pattern=None, multi=None, anime_type=None):
    """Manipulate an episode naming pattern and then fills the template in.

    :param pattern:
    :type pattern: str
    :param multi:
    :type multi: bool
    :param anime_type:
    :type anime_type: int
    :return:
    :rtype: str
    """
    if pattern is None:
        pattern = app.NAMING_PATTERN

    if multi is None:
        multi = app.NAMING_MULTI_EP

    if app.NAMING_CUSTOM_ANIME:
        if anime_type is None:
            anime_type = app.NAMING_ANIME
    else:
        anime_type = 3

    replace_map = self.__replace_map()

    result_name = pattern

    # if there's no release group in the db, let the user know we replaced it
    if replace_map["%RG"] and replace_map["%RG"] != app.UNKNOWN_RELEASE_GROUP:
        if not hasattr(self, "release_group") or not self.release_group:
            log.debug(
                "{id}: Episode has no release group, replacing it with {rg}",
                {"id": self.series.series_id, "rg": replace_map["%RG"]},
            )
            self.release_group = replace_map[
                "%RG"
            ]  # if release_group is not in the db, put it there

    # if there's no release name then replace it with a reasonable facsimile
    if not replace_map["%RN"]:
        if self.series.air_by_date or self.series.sports:
            result_name = result_name.replace(
                "%RN", "%S.N.%A.D.%E.N-" + replace_map["%RG"]
            )
            result_name = result_name.replace(
                "%rn", "%s.n.%A.D.%e.n-" + replace_map["%RG"].lower()
            )

        elif anime_type != 3:
            result_name = result_name.replace(
                "%RN", "%S.N.%AB.%E.N-" + replace_map["%RG"]
            )
            result_name = result_name.replace(
                "%rn", "%s.n.%ab.%e.n-" + replace_map["%RG"].lower()
            )

        else:
            result_name = result_name.replace(
                "%RN", "%S.N.S%0SE%0E.%E.N-" + replace_map["%RG"]
            )
            result_name = result_name.replace(
                "%rn", "%s.n.s%0se%0e.%e.n-" + replace_map["%RG"].lower()
            )

    if not replace_map["%RT"]:
        result_name = re.sub("([ _.-]*)%RT([ _.-]*)", r"\2", result_name)

    # split off ep name part only
    name_groups = re.split(r"[\\/]", result_name)

    # figure out the double-ep numbering style for each group, if applicable
    for cur_name_group in name_groups:
        season_ep_regex = r"""
                                (?P<pre_sep>[ _.-]*)
                                ((?:s(?:eason|eries)?\s*)?%0?S(?![._]?N))
                                (.*?)
                                (%0?E(?![._]?N))
                                (?P<post_sep>[ _.-]*)
                              """
        ep_only_regex = r"(E?%0?E(?![._]?N))"

        # try the normal way
        season_ep_match = re.search(season_ep_regex, cur_name_group, re.I | re.X)
        ep_only_match = re.search(ep_only_regex, cur_name_group, re.I | re.X)

        # if we have a season and episode then collect the necessary data
        if season_ep_match:
            season_format = season_ep_match.group(2)
            ep_sep = season_ep_match.group(3)
            ep_format = season_ep_match.group(4)
            sep = season_ep_match.group("pre_sep")
            if not sep:
                sep = season_ep_match.group("post_sep")
            if not sep:
                sep = " "

            # force 2-3-4 format if they chose to extend
            if multi in (
                NAMING_EXTEND,
                NAMING_LIMITED_EXTEND,
                NAMING_LIMITED_EXTEND_E_PREFIXED,
            ):
                ep_sep = "-"

            regex_used = season_ep_regex

        # if there's no season then there's not much choice so we'll just force them to use 03-04-05 style
        elif ep_only_match:
            season_format = ""
            ep_sep = "-"
            ep_format = ep_only_match.group(1)
            sep = ""
            regex_used = ep_only_regex

        else:
            continue

        # we need at least this much info to continue
        if not ep_sep or not ep_format:
            continue

        # start with the ep string, eg. E03
        ep_string = self.__format_string(ep_format.upper(), replace_map)
        for other_ep in self.related_episodes:
            # for limited extend we only append the last ep
            if (
                multi in (NAMING_LIMITED_EXTEND, NAMING_LIMITED_EXTEND_E_PREFIXED)
                and other_ep != self.related_episodes[-1]
            ):
                continue

            elif multi == NAMING_DUPLICATE:
                # add " - S01"
                ep_string += sep + season_format

            elif multi == NAMING_SEPARATED_REPEAT:
                ep_string += sep

            # add "E04"
            ep_string += ep_sep

            if multi == NAMING_LIMITED_EXTEND_E_PREFIXED:
                ep_string += "E"

            ep_string += other_ep.__format_string(
                ep_format.upper(), other_ep.__replace_map()
            )

        if anime_type != 3:
            if self.absolute_number == 0:
                cur_absolute_number = self.episode
            else:
                cur_absolute_number = self.absolute_number

            if self.season != 0:  # don't set absolute numbers if we are on specials !
                if anime_type == 1:  # this crazy person wants both ! (note: +=)
                    ep_string += sep + "%(#)03d" % {"#": cur_absolute_number}
                elif (
                    anime_type == 2
                ):  # total anime freak only need the absolute number ! (note: =)
                    ep_string = "%(#)03d" % {"#": cur_absolute_number}

                for rel_ep in self.related_episodes:
                    if rel_ep.absolute_number != 0:
                        ep_string += "-" + "%(#)03d" % {"#": rel_ep.absolute_number}
                    else:
                        ep_string += "-" + "%(#)03d" % {"#": rel_ep.episode}

        regex_replacement = None
        if anime_type == 2:
            regex_replacement = r"\g<pre_sep>" + ep_string + r"\g<post_sep>"
        elif season_ep_match:
            regex_replacement = r"\g<pre_sep>\g<2>\g<3>" + ep_string + r"\g<post_sep>"
        elif ep_only_match:
            regex_replacement = ep_string

        if regex_replacement:
            # fill out the template for this piece and then insert this piece into the actual pattern
            cur_name_group_result = re.sub(
                "(?i)(?x)" + regex_used, regex_replacement, cur_name_group
            )
            # cur_name_group_result = cur_name_group.replace(ep_format, ep_string)
            result_name = result_name.replace(cur_name_group, cur_name_group_result)

    result_name = self.__format_string(result_name, replace_map)

    log.debug(
        "{id}: Formatting pattern: {pattern} -> {result}",
        {"id": self.series.series_id, "pattern": pattern, "result": result_name},
    )

    return result_name


# Traceback (OSError)
2018-02-03 10:00:23 DEBUG    POSTPROCESSOR :: [4e0d16b] Retrieving episode object for The Disastrous Life of Saiki K S01E02
2018-02-03 10:00:23 DEBUG    POSTPROCESSOR :: [4e0d16b] The episode file has a quality in it, using that: 720p HDTV
2018-02-03 10:00:24 DEBUG    POSTPROCESSOR :: [4e0d16b] This episode was found in history as SNATCHED.
2018-02-03 10:00:24 DEBUG    POSTPROCESSOR :: [4e0d16b] Quality of the episode we are processing: 720p HDTV
2018-02-03 10:00:24 DEBUG    POSTPROCESSOR :: [4e0d16b] Snatch in history: True
2018-02-03 10:00:24 DEBUG    POSTPROCESSOR :: [4e0d16b] Manually snatched: False
2018-02-03 10:00:24 DEBUG    POSTPROCESSOR :: [4e0d16b] Info hash: 9d44e1c4d186725fdc024326d8692bde9353eedb
2018-02-03 10:00:24 DEBUG    POSTPROCESSOR :: [4e0d16b] NZB: False
2018-02-03 10:00:24 DEBUG    POSTPROCESSOR :: [4e0d16b] Current quality: 720p HDTV
2018-02-03 10:00:24 DEBUG    POSTPROCESSOR :: [4e0d16b] New quality: 720p HDTV
2018-02-03 10:00:24 DEBUG    POSTPROCESSOR :: [4e0d16b] Proper: False
2018-02-03 10:00:24 DEBUG    POSTPROCESSOR :: [4e0d16b] This episode is a priority download: True
2018-02-03 10:00:24 INFO     POSTPROCESSOR :: [4e0d16b] New file: /srv/dev-disk-by-label-3TBJBOD/Complete/Series/[Davinci] Saiki Kusuo no Psi-nan 2 - 01 [720p][C53F5DBC].mkv
2018-02-03 10:00:24 INFO     POSTPROCESSOR :: [4e0d16b] New size: 219.52 MB
2018-02-03 10:00:24 DEBUG    POSTPROCESSOR :: [4e0d16b] There is no existing file so there's no worries about replacing it
2018-02-03 10:00:24 INFO     POSTPROCESSOR :: [4e0d16b] This download is marked a priority download so I'm going to replace an existing file if I find one
2018-02-03 10:00:24 DEBUG    POSTPROCESSOR :: [4e0d16b] Trying to determine free space on destination drive
2018-02-03 10:00:24 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] GET URL: https://anizb.org/api/?q=Saiki%20Kusuo%20no%20Psi-Nan*027 [Status: 200]
2018-02-03 10:00:24 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] User-Agent: Medusa/0.1.23 (Linux; 4.9.0-4-amd64; ff070e6c-0846-11e8-b008-0014fd16b29a)
2018-02-03 10:00:24 DEBUG    POSTPROCESSOR :: [4e0d16b] Found release name [Davinci] Saiki Kusuo no Psi-nan 2 - 01 [720p][C53F5DBC]
2018-02-03 10:00:24 DEBUG    POSTPROCESSOR :: [4e0d16b] Found release name [Davinci] Saiki Kusuo no Psi-nan 2 - 01 [720p][C53F5DBC]
2018-02-03 10:00:24 INFO     SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] Returned xml contained no results
2018-02-03 10:00:24 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] Search string: The Disastrous Life of Saiki K*27
2018-02-03 10:00:24 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] GET URL: https://anizb.org/api/?q=The%20Disastrous%20Life%20of%20Saiki%20K*27 [Status: 200]
2018-02-03 10:00:24 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] User-Agent: Medusa/0.1.23 (Linux; 4.9.0-4-amd64; ff070e6c-0846-11e8-b008-0014fd16b29a)
2018-02-03 10:00:24 INFO     SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] Returned xml contained no results
2018-02-03 10:00:24 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] Search string: The Disastrous Life of Saiki K*027
2018-02-03 10:00:24 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] GET URL: https://anizb.org/api/?q=The%20Disastrous%20Life%20of%20Saiki%20K*027 [Status: 200]
2018-02-03 10:00:24 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] User-Agent: Medusa/0.1.23 (Linux; 4.9.0-4-amd64; ff070e6c-0846-11e8-b008-0014fd16b29a)
2018-02-03 10:00:24 INFO     SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] Returned xml contained no results
2018-02-03 10:00:24 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] Found 6 unique items
2018-02-03 10:00:24 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] Found qualities: [16, 4]
2018-02-03 10:00:24 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] No unknown qualities in results
2018-02-03 10:00:25 DEBUG    POSTPROCESSOR :: [4e0d16b] Folder name (Series) appears to be a valid release name. Using it.
2018-02-03 10:00:25 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] Scene numbering enabled series The Disastrous Life of Saiki K is anime
2018-02-03 10:00:25 DEBUG    POSTPROCESSOR :: [4e0d16b] Matched release [Davinci] Saiki Kusuo no Psi-nan 2 - 01 [720p][C53F5DBC] to a series in your database: The Disastrous Life of Saiki K
2018-02-03 10:00:25 DEBUG    POSTPROCESSOR :: [4e0d16b] Parsed [Davinci] Saiki Kusuo no Psi-nan 2 - 01 [720p][C53F5DBC] into release_group: Davinci, title: Saiki Kusuo no Psi-nan, episode: [], absolute_episode: [1, 2], screen_size: 720p, crc32: C53F5DBC, type: episode, parsing_time: 0.387208938599, total_time: 0.387750864029, quality: 720p HDTV, season: None
2018-02-03 10:00:25 DEBUG    POSTPROCESSOR :: [4e0d16b] Found codec for The Disastrous Life of Saiki K The Disastrous Life of a Psychic + The Worst of the Worst?! Riki Nendou + Shun Kaidou, AKA The Jet-Black Wings + Intelligent and Beautiful! Kokomi Teruhashi & Hot-Blooded! Dodgeball! + Reach Him! Sign of Love + Saiki Family Home Renovation?! Drastic Makeover!! + Deceive! Mind Control
2018-02-03 10:00:26 DEBUG    POSTPROCESSOR :: [4e0d16b] Matched release [Davinci] Saiki Kusuo no Psi-nan 2 - 01 [720p][C53F5DBC] to a series in your database: The Disastrous Life of Saiki K
2018-02-03 10:00:26 DEBUG    POSTPROCESSOR :: [4e0d16b] Parsed [Davinci] Saiki Kusuo no Psi-nan 2 - 01 [720p][C53F5DBC] into release_group: Davinci, title: Saiki Kusuo no Psi-nan, episode: [], absolute_episode: [1, 2], screen_size: 720p, crc32: C53F5DBC, type: episode, parsing_time: 0.28431391716, total_time: 0.285199165344, quality: 720p HDTV, season: None
2018-02-03 10:00:26 DEBUG    POSTPROCESSOR :: [4e0d16b] Found codec for The Disastrous Life of Saiki K Hot-Blooded! Dodgeball! + Reach Him! Sign of Love + Saiki Family Home Renovation?! Drastic Makeover!! + Deceive! Mind Control
2018-02-03 10:00:26 DEBUG    POSTPROCESSOR :: [4e0d16b] 313435: Formatting pattern: %SN - S%0SE%0E - %EN -> The Disastrous Life of Saiki K - S01E01E02 - The Disastrous Life of a Psychic + The Worst of the Worst! Riki Nendou + Shun Kaidou, AKA The Jet-Black Wings + Intelligent and Beautiful! Kokomi Teruhashi & Hot-Blooded! Dodgeball! + Reach Him! Sign of Love + Saiki Family Home Renovation! Drastic Makeover!! + Deceive! Mind Control
2018-02-03 10:00:26 DEBUG    POSTPROCESSOR :: [4e0d16b] Matched release [Davinci] Saiki Kusuo no Psi-nan 2 - 01 [720p][C53F5DBC] to a series in your database: The Disastrous Life of Saiki K
2018-02-03 10:00:26 DEBUG    POSTPROCESSOR :: [4e0d16b] Parsed [Davinci] Saiki Kusuo no Psi-nan 2 - 01 [720p][C53F5DBC] into release_group: Davinci, title: Saiki Kusuo no Psi-nan, episode: [], absolute_episode: [1, 2], screen_size: 720p, crc32: C53F5DBC, type: episode, parsing_time: 0.277107954025, total_time: 0.277932882309, quality: 720p HDTV, season: None
2018-02-03 10:00:26 DEBUG    POSTPROCESSOR :: [4e0d16b] Found codec for The Disastrous Life of Saiki K The Disastrous Life of a Psychic + The Worst of the Worst?! Riki Nendou + Shun Kaidou, AKA The Jet-Black Wings + Intelligent and Beautiful! Kokomi Teruhashi & Hot-Blooded! Dodgeball! + Reach Him! Sign of Love + Saiki Family Home Renovation?! Drastic Makeover!! + Deceive! Mind Control
2018-02-03 10:00:26 DEBUG    POSTPROCESSOR :: [4e0d16b] 313435: Formatting pattern: Season %0S -> Season 01
2018-02-03 10:00:26 DEBUG    POSTPROCESSOR :: [4e0d16b] Destination folder for this episode: /media/bigdisk/Anime/The Disastrous Life of Saiki K/Season 01
2018-02-03 10:00:26 DEBUG    POSTPROCESSOR :: [4e0d16b] Checking if the path /media/bigdisk/Anime/The Disastrous Life of Saiki K/Season 01 already exists
2018-02-03 10:00:26 DEBUG    POSTPROCESSOR :: [4e0d16b] Folder /media/bigdisk/Anime/The Disastrous Life of Saiki K/Season 01/ didn't exist, creating it
2018-02-03 10:00:26 DEBUG    POSTPROCESSOR :: [4e0d16b] Setting permissions for /media/bigdisk/Anime/The Disastrous Life of Saiki K/Season 01 to 1533 as parent directory has 1533
2018-02-03 10:00:26 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] Scene exception lookup got indexer ID 313435, using that
2018-02-03 10:00:27 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] 313435: Season and episode lookup for The Disastrous Life of Saiki K using absolute number 6
2018-02-03 10:00:27 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] 313435: Found season and episode which is The Disastrous Life of Saiki K S01E06
2018-02-03 10:00:27 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] Scene numbering enabled series The Disastrous Life of Saiki K using indexer for absolute 6: None
2018-02-03 10:00:27 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] 313435: Season and episode lookup for The Disastrous Life of Saiki K using absolute number 26
2018-02-03 10:00:27 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] 313435: Found season and episode which is The Disastrous Life of Saiki K S02E02
2018-02-03 10:00:27 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] Scene numbering enabled series The Disastrous Life of Saiki K using indexer for absolute 26: None
2018-02-03 10:00:27 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] 313435: Season and episode lookup for The Disastrous Life of Saiki K using absolute number 27
2018-02-03 10:00:27 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] 313435: Found season and episode which is The Disastrous Life of Saiki K S02E03
2018-02-03 10:00:27 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] Scene numbering enabled series The Disastrous Life of Saiki K using indexer for absolute 27: None
2018-02-03 10:00:27 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] 313435: Season and episode lookup for The Disastrous Life of Saiki K using absolute number 28
2018-02-03 10:00:27 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] 313435: Found season and episode which is The Disastrous Life of Saiki K S02E04
2018-02-03 10:00:27 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] Scene numbering enabled series The Disastrous Life of Saiki K using indexer for absolute 28: None
2018-02-03 10:00:27 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] 313435: Season and episode lookup for The Disastrous Life of Saiki K using absolute number 29
2018-02-03 10:00:27 DEBUG    POSTPROCESSOR :: [4e0d16b] No associated files were found for /srv/dev-disk-by-label-3TBJBOD/Complete/Series/[Davinci] Saiki Kusuo no Psi-nan 2 - 01 [720p][C53F5DBC].mkv
2018-02-03 10:00:27 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] 313435: No entries found in show: The Disastrous Life of Saiki K
2018-02-03 10:00:27 DEBUG    POSTPROCESSOR :: [4e0d16b] Moving file from /srv/dev-disk-by-label-3TBJBOD/Complete/Series/[Davinci] Saiki Kusuo no Psi-nan 2 - 01 [720p][C53F5DBC].mkv to /media/bigdisk/Anime/The Disastrous Life of Saiki K/Season 01/The Disastrous Life of Saiki K - S01E01E02 - The Disastrous Life of a Psychic + The Worst of the Worst! Riki Nendou + Shun Kaidou, AKA The Jet-Black Wings + Intelligent and Beautiful! Kokomi Teruhashi & Hot-Blooded! Dodgeball! + Reach Him! Sign of Love + Saiki Family Home Renovation! Drastic Makeover!! + Deceive! Mind Control.mkv 
2018-02-03 10:00:27 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] Scene numbering enabled series The Disastrous Life of Saiki K using indexer for absolute 29: None
2018-02-03 10:00:27 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] 313435: Season and episode lookup for The Disastrous Life of Saiki K using absolute number 30
2018-02-03 10:00:27 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] 313435: No entries found in show: The Disastrous Life of Saiki K
2018-02-03 10:00:27 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] Scene numbering enabled series The Disastrous Life of Saiki K using indexer for absolute 30: None
2018-02-03 10:00:27 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] Error during parsing of release name: [AnimeRG].The.Disastrous.Life.of.Saiki.K..-.06.(Short.Eps.26-30).[1080p].[x265].[pseudo], with error: Scene numbering results episodes from seasons [None, 1, 2], (i.e. more than one) and Medusa does not support this. Sorry.
2018-02-03 10:00:27 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] Using cached parse result for [Davinci].Saiki.Kusuo.no.Psi-nan.2.-.01.[720p][C53F5DBC]
2018-02-03 10:00:27 DEBUG    SEARCHQUEUE-BACKLOG-313435 :: [Anizb] :: [4e0d16b] The result [Davinci].Saiki.Kusuo.no.Psi-nan.2.-.01.[720p][C53F5DBC] doesn't seem to match an episode that we are currently trying to snatch, skipping it
2018-02-03 10:00:27 ERROR    POSTPROCESSOR :: [4e0d16b] OSError: 
Traceback (most recent call last):
  File "/opt/medusa/medusa/helpers/__init__.py", line 285, in copy_file
    shutil.copyfile(src_file, dest_file)
  File "/opt/medusa/lib/shutil_custom/__init__.py", line 42, in copyfile_custom
    fout = os.open(dst, WRITE_FLAGS)
OSError: [Errno 36] File name too long: '/media/bigdisk/Anime/The Disastrous Life of Saiki K/Season 01/The Disastrous Life of Saiki K - S01E01E02 - The Disastrous Life of a Psychic + The Worst of the Worst! Riki Nendou + Shun Kaidou, AKA The Jet-Black Wings + Intelligent and Beautiful! Kokomi Teruhashi & Hot-Blooded! Dodgeball! + Reach Him! Sign of Love + Saiki Family Home Renovation! Drastic Makeover!! + Deceive! Mind Control.mkv'

# Fixed code
def _format_pattern(self, pattern=None, multi=None, anime_type=None):
    """Manipulate an episode naming pattern and then fills the template in.

    :param pattern:
    :type pattern: str
    :param multi:
    :type multi: bool
    :param anime_type:
    :type anime_type: int
    :return:
    :rtype: str
    """
    if pattern is None:
        pattern = app.NAMING_PATTERN

    if multi is None:
        multi = app.NAMING_MULTI_EP

    if app.NAMING_CUSTOM_ANIME:
        if anime_type is None:
            anime_type = app.NAMING_ANIME
    else:
        anime_type = 3

    replace_map = self.__replace_map()

    result_name = pattern

    # if there's no release group in the db, let the user know we replaced it
    if replace_map["%RG"] and replace_map["%RG"] != app.UNKNOWN_RELEASE_GROUP:
        if not hasattr(self, "release_group") or not self.release_group:
            log.debug(
                "{id}: Episode has no release group, replacing it with {rg}",
                {"id": self.series.series_id, "rg": replace_map["%RG"]},
            )
            self.release_group = replace_map[
                "%RG"
            ]  # if release_group is not in the db, put it there

    # if there's no release name then replace it with a reasonable facsimile
    if not replace_map["%RN"]:
        if self.series.air_by_date or self.series.sports:
            result_name = result_name.replace(
                "%RN", "%S.N.%A.D.%E.N-" + replace_map["%RG"]
            )
            result_name = result_name.replace(
                "%rn", "%s.n.%A.D.%e.n-" + replace_map["%RG"].lower()
            )

        elif anime_type != 3:
            result_name = result_name.replace(
                "%RN", "%S.N.%AB.%E.N-" + replace_map["%RG"]
            )
            result_name = result_name.replace(
                "%rn", "%s.n.%ab.%e.n-" + replace_map["%RG"].lower()
            )

        else:
            result_name = result_name.replace(
                "%RN", "%S.N.S%0SE%0E.%E.N-" + replace_map["%RG"]
            )
            result_name = result_name.replace(
                "%rn", "%s.n.s%0se%0e.%e.n-" + replace_map["%RG"].lower()
            )

    if not replace_map["%RT"]:
        result_name = re.sub("([ _.-]*)%RT([ _.-]*)", r"\2", result_name)

    # split off ep name part only
    name_groups = re.split(r"[\\/]", result_name)

    # figure out the double-ep numbering style for each group, if applicable
    for cur_name_group in name_groups:
        season_ep_regex = r"""
                                (?P<pre_sep>[ _.-]*)
                                ((?:s(?:eason|eries)?\s*)?%0?S(?![._]?N))
                                (.*?)
                                (%0?E(?![._]?N))
                                (?P<post_sep>[ _.-]*)
                              """
        ep_only_regex = r"(E?%0?E(?![._]?N))"

        # try the normal way
        season_ep_match = re.search(season_ep_regex, cur_name_group, re.I | re.X)
        ep_only_match = re.search(ep_only_regex, cur_name_group, re.I | re.X)

        # if we have a season and episode then collect the necessary data
        if season_ep_match:
            season_format = season_ep_match.group(2)
            ep_sep = season_ep_match.group(3)
            ep_format = season_ep_match.group(4)
            sep = season_ep_match.group("pre_sep")
            if not sep:
                sep = season_ep_match.group("post_sep")
            if not sep:
                sep = " "

            # force 2-3-4 format if they chose to extend
            if multi in (
                NAMING_EXTEND,
                NAMING_LIMITED_EXTEND,
                NAMING_LIMITED_EXTEND_E_PREFIXED,
            ):
                ep_sep = "-"

            regex_used = season_ep_regex

        # if there's no season then there's not much choice so we'll just force them to use 03-04-05 style
        elif ep_only_match:
            season_format = ""
            ep_sep = "-"
            ep_format = ep_only_match.group(1)
            sep = ""
            regex_used = ep_only_regex

        else:
            continue

        # we need at least this much info to continue
        if not ep_sep or not ep_format:
            continue

        # start with the ep string, eg. E03
        ep_string = self.__format_string(ep_format.upper(), replace_map)
        for other_ep in self.related_episodes:
            # for limited extend we only append the last ep
            if (
                multi in (NAMING_LIMITED_EXTEND, NAMING_LIMITED_EXTEND_E_PREFIXED)
                and other_ep != self.related_episodes[-1]
            ):
                continue

            elif multi == NAMING_DUPLICATE:
                # add " - S01"
                ep_string += sep + season_format

            elif multi == NAMING_SEPARATED_REPEAT:
                ep_string += sep

            # add "E04"
            ep_string += ep_sep

            if multi == NAMING_LIMITED_EXTEND_E_PREFIXED:
                ep_string += "E"

            ep_string += other_ep.__format_string(
                ep_format.upper(), other_ep.__replace_map()
            )

        if anime_type != 3:
            if self.absolute_number == 0:
                cur_absolute_number = self.episode
            else:
                cur_absolute_number = self.absolute_number

            if self.season != 0:  # don't set absolute numbers if we are on specials !
                if anime_type == 1:  # this crazy person wants both ! (note: +=)
                    ep_string += sep + "%(#)03d" % {"#": cur_absolute_number}
                elif (
                    anime_type == 2
                ):  # total anime freak only need the absolute number ! (note: =)
                    ep_string = "%(#)03d" % {"#": cur_absolute_number}

                for rel_ep in self.related_episodes:
                    if rel_ep.absolute_number != 0:
                        ep_string += "-" + "%(#)03d" % {"#": rel_ep.absolute_number}
                    else:
                        ep_string += "-" + "%(#)03d" % {"#": rel_ep.episode}

        regex_replacement = None
        if anime_type == 2:
            regex_replacement = r"\g<pre_sep>" + ep_string + r"\g<post_sep>"
        elif season_ep_match:
            regex_replacement = r"\g<pre_sep>\g<2>\g<3>" + ep_string + r"\g<post_sep>"
        elif ep_only_match:
            regex_replacement = ep_string

        if regex_replacement:
            # fill out the template for this piece and then insert this piece into the actual pattern
            cur_name_group_result = re.sub(
                "(?i)(?x)" + regex_used, regex_replacement, cur_name_group
            )
            # cur_name_group_result = cur_name_group.replace(ep_format, ep_string)
            result_name = result_name.replace(cur_name_group, cur_name_group_result)

    parsed_result_name = self.__format_string(result_name, replace_map)

    # With the episode name filenames tend to grow very large. Worst case scenario we even need to add `-thumb.jpg`
    # to the filename. To make sure we stay under the 255 character limit, we're working with 244 chars, taking into
    # account the thumbnail.
    if len(parsed_result_name) > 244 and any(
        ["%E.N" in result_name, "%EN" in result_name, "%E_N" in result_name]
    ):
        for remove_pattern in ("%E.N", "%EN", "%E_N"):
            result_name = result_name.replace(remove_pattern, "")
        # The Episode name can be appended with a - or . in between. Therefor we're removing it.
        # Creating a clean filename.
        result_name = result_name.strip("-. ")
        parsed_result_name = self.__format_string(result_name, replace_map)
        log.debug(
            "{id}: Cutting off the episode name, as the total filename is too long. > 255 chars.",
            {"id": self.series.series_id},
        )

    log.debug(
        "{id}: Formatting pattern: {pattern} -> {result}",
        {
            "id": self.series.series_id,
            "pattern": result_name,
            "result": parsed_result_name,
        },
    )

    return parsed_result_name