from typing import Tuple
from typing import List
import string
import re


def _parse_raster_pattern(raster_pattern: str) -> Tuple[List[str], str, str]:
    """Parse a raster pattern string using Python format syntax.

    Extracts names of unique placeholders, a glob pattern
    and a regular expression to retrieve files matching the given pattern.

    Example:

        >>> _parse_raster_pattern('{key1}/{key2}_{}.tif')
        (['key1', 'key2'], '*/*_*.tif', '(?P<key1>[^\\W_]+)/(?P<key2>[^\\W_]+)_.*?\\.tif')

    """

    # raises ValueError on invalid patterns
    parsed_value = string.Formatter().parse(raster_pattern)

    keys: List[str] = []
    glob_pattern: List[str] = []
    regex_pattern: List[str] = []

    for before_field, field_name, _, _ in parsed_value:
        glob_pattern += before_field
        regex_pattern += re.escape(before_field)

        if field_name is None:
            # no placeholder
            continue

        glob_pattern.append('*')

        if field_name == '':
            # unnamed placeholder
            regex_pattern.append('.*?')
        elif field_name in keys:
            # duplicate placeholder
            key_group_number = keys.index(field_name) + 1
            regex_pattern.append(rf'\{key_group_number}')
        else:
            # new placeholder
            keys.append(field_name)
            regex_pattern += rf'(?P<{field_name}>[^\W_]+)'

    return keys, ''.join(glob_pattern), ''.join(regex_pattern)