from aqua.core.configurer import ConfigPath
from .util import to_list

def replace_intake_vars(path: str, catalog: str | None = None) -> str:
    """
    Replace the intake jinja vars into a string for a predefined catalog

    Args:
        path: the original path that you want to update with the intake variables
        catalog:  the catalog name where the intake vars must be read

    Returns:
        The updated path with the intake variables replaced.
    """

    # We exploit of configurerto get info on intake_vars so that we can replace them in the urlpath
    Configurer = ConfigPath(catalog=catalog)
    _, intake_vars = Configurer.get_machine_info()
    
    # loop on available intake_vars, replace them in the urlpath
    for name in intake_vars.keys():
        replacepath = intake_vars[name]
        if replacepath is not None and replacepath in path:
            # quotes used to ensure that then you can read the source
            path = path.replace(replacepath, "{{ " + name + " }}")

    return path


def replace_urlpath_jinja(block: dict, value: str, name: str, default: str | None = None) -> dict:
    """
    Replace the urlpath in the catalog entry with the given jinja parameter and
    add the parameter to the parameters block

    Args:
        block (dict): The catalog entry generated by `catalog_entry_details' to be updated
        value (str): The value to replace in the urlpath (e.g., 'r1', 'global', 'mean')
        name (str): The name of the parameter to add to the parameters block
                    and to be used in the urlpath (e.g., 'realization', 'region', 'stat')
        default(optional, str): The default value for the parameter. If the value is equal to the default,
                 no parameter is created and the urlpath is not modified.
        

    Returns:
        dict: The updated catalog entry block
    """
    if not value:
        return block
    
    # TODO: verify this is needed 
    # return if the value is the default one, no need to create a parameter
    if default is not None and value == default:
        return block

    # this loop is a bit tricky but is made to ensure that the right value is replaced
    # it works on multiple urlpath (list) or single urlpath (str)
    urlpath = to_list(block['args']['urlpath'])
    for i, _ in enumerate(urlpath):
        for character in ['_', '/', '.']:
            urlpath[i] = urlpath[i].replace(character + value + character, character + "{{" + name + "}}" + character)
    block['args']['urlpath'] = urlpath if len(urlpath) > 1 else urlpath[0]

    # add the parameter to the parameters block
    if 'parameters' not in block:
        block['parameters'] = {}
    if name not in block['parameters']:
        block['parameters'][name] = {}
        block['parameters'][name]['description'] = f"Parameter {name}"
        block['parameters'][name]['default'] = value
        block['parameters'][name]['type'] = 'str'
        block['parameters'][name]['allowed'] = [value]
    else:
        if value not in block['parameters'][name]['allowed']:
            block['parameters'][name]['allowed'].append(value)

    return block


def replace_urlpath_wildcard(block: dict, value: str) -> dict:
    """
    Replace the urlpath in the catalog entry with "*" 

    Args:
        block (dict): The catalog entry generated by `catalog_entry_details' to be updated
        value (str): The value to replace in the urlpath (e.g., 'r1', 'global', 'mean')

    Returns:
        dict: The updated catalog entry block
    """
    if not value:
        return block
    
    # this loop is a bit tricky but is made to ensure that the right value is replaced
    for character in ['_', '/', '.']:
        block['args']['urlpath'] = block['args']['urlpath'].replace(
            character + value + character, character + "*" + character)
        
    return block