import re


def title_output_replace(input_title_output, metadata_dict, data_dict, rel_channels_dict, is_title = False, custom_vars = None):
    """Substitute %VAR% variables with provided values and constants.
    
    Given a title (or output path) string template, replace %VAR% 
    variables with the appropriate value or constant.
    
    Variables supported include:
    
    * %EXPERIMENT_ID% - Experiment ID, sourced from metadata_dict.
    * %INSTRUMENT_SAT% - Instrument/satellite ID, sourced from
      metadata_dict.
    * %CHANNEL% - Channel number, sourced from metadata_dict.
    * %RELCHANNEL% - Relative channel number, indirectly sourced from
      rel_channels_dict.
    * %FREQUENCY% - Frequency of the selected channel, sourced from the
      frequency field in data_dict.
    * %ASSIMILATION_STATUS% - Placeholder for the assimilation status,
      which is determined from the iuse field in data_dict (not done
      here).
    * %START_DATE% - Start date in YYYYMMDD format, sourced from
      metadata_dict.
    * %END_DATE% - End date in YYYYMMDD format, sourced from
      metadata_dict.
    * Additional custom %VARS% sourced from custom_vars, if specified.
    
    Args:
        input_title_output (str): The string with the title (or output 
            path) template.
        metadata_dict (dict): The metadata dictionary containing data
            source information.
        data_dict (dict): The data dictionary to retrieve values from
            for certain %VAR% variables. See get_data() help (in 
            data.py) for more information on its format.
        rel_channels_dict (dict): The relative channels dictionary to
            map relative channels to actual data channels. Its keys are 
            the relative channels, and its values are the actual data 
            channels. (In this case, the mapping is reversed later to 
            allow easy conversion from data channel to relative 
            channel.)
        is_title (bool): Boolean indicating whether the string templace
            is a title or not. This affects how and what variables are 
            replaced. By default, this is set to False.
        custom_vars (dict): Dictionary containing custom variables to
            be replaced. Its keys are %VAR% variables without the 
            percent sign, and its values are what should take their 
            places. For instance, given { "TESTVAR": "test123" }, the 
            template "%TESTVAR%" should be replaced with "test123". By 
            default, this is set to None - this argument is optional if 
            there are no custom variables.
    
    Returns:
        str: A string with %VAR% variables replaced with the 
        appropriate value or constant. Some %VAR% variables may not be 
        replaced if they do not exist, or certain conditions are not 
        met.
    """
    # Replace experiment ID variable
    input_title_output = input_title_output.replace("%EXPERIMENT_ID%", metadata_dict["experiment_id"])
    
    # Capitalize %INSTRUMENT_SAT% if we're using it in a title.
    if is_title:
        input_title_output = input_title_output.replace("%INSTRUMENT_SAT%", metadata_dict["instrument_sat"].upper())
    else:
        input_title_output = input_title_output.replace("%INSTRUMENT_SAT%", metadata_dict["instrument_sat"])
    
    # Replace data channel variable
    input_title_output = input_title_output.replace("%CHANNEL%", str(metadata_dict["channel"]))
    
    # Reverse the channel map
    # Original: rel_channel -> actual data channel
    # Inverted: actual data channel -> rel_channel
    rel_channels_inv_map = dict(zip(rel_channels_dict.values(), rel_channels_dict.keys()))
    input_title_output = input_title_output.replace("%RELCHANNEL%", str(rel_channels_inv_map[metadata_dict["channel"]]))
    
    # Ensure that we have adequate data to determine frequency.
    # If we do, replace the frequency variable!
    if data_dict and "frequency" in data_dict:
        input_title_output = input_title_output.replace("%FREQUENCY%", str(data_dict["frequency"]))
    
    # Replace assimilation status placeholder... only if it's a title.
    if is_title:
        input_title_output = input_title_output.replace("%ASSIMILATION_STATUS%", "    .......................")
    
    # Replace date variables
    input_title_output = input_title_output.replace("%START_DATE%", str(metadata_dict['start_year']).zfill(4) + str(metadata_dict['start_month']).zfill(2) + str(metadata_dict['start_day']).zfill(2))
    input_title_output = input_title_output.replace("%END_DATE%", str(metadata_dict['end_year']).zfill(4) + str(metadata_dict['end_month']).zfill(2) + str(metadata_dict['end_day']).zfill(2))
    
    # Custom vars
    if custom_vars:
        for custom_var in custom_vars:
            # Do a case insensitive replace
            replace_re = re.compile(re.escape('%'+custom_var+'%'), re.IGNORECASE)
            input_title_output = replace_re.sub(custom_vars[custom_var], input_title_output)
    
    return input_title_output