import itertools
import copy


def _expand_configs(configs):
    """
    Create edit strategies
    Args:
        configs (list): List of dictionaries

    Returns:
        (list) Expanded configs

    Detailed description:
    Expanding a config file should look like the following:

    We start with a config file (.yml):

    (YAML)
    ```
    path: example.py
    configurations:
      - line_number: 1
        variable: LEARNING_RATE
        value: [0.1, 0.2, 0.3]
      - line_number: 2
        variable: DECAY
        value: [0.1, 0.2]
    ---
    path: example_2.py
    configurations:
      - line_number: 1
        variable: FACTOR
        value: 2
    ```

    Parsing this using PyYAML yields:

    (dictionary)
    ```
    [{'path': 'example.py',
      'configurations': [{'line_number': 1,
        'variable': 'LEARNING_RATE',
        'value': [0.1, 0.2, 0.3]},
       {'line_number': 2, 'variable': 'DECAY', 'value': [0.1, 0.2]}]},
     {'path': 'example_2.py',
      'configurations': [{'line_number': 1, 'variable': 'FACTOR', 'value': 2}]}]
    ```

    and parsing this further to enumerate all edit configurations should look like:

    (edit strategy prototype)
    ```
    [ -- edit strategy level
     [ -- edit directive level
        (example.py, [(1, LEARNING_RATE, 0.1), (2, DECAY, 0.1)]),
        (example_2.py, [(1, FACTOR, 2)]
     ],
     [
        (example.py, [(1, LEARNING_RATE, 0.1), (2, DECAY, 0.2)]),
        (example_2.py, [(1, FACTOR, 2)]
     ],
     [
        (example.py, [(1, LEARNING_RATE, 0.2), (2, DECAY, 0.1)]),
        (example_2.py, [(1, FACTOR, 2)]
     ],
     [
        (example.py, [(1, LEARNING_RATE, 0.2), (2, DECAY, 0.2)]),
        (example_2.py, [(1, FACTOR, 2)]
     ],
     [
        (example.py, [(1, LEARNING_RATE, 0.3), (2, DECAY, 0.1)]),
        (example_2.py, [(1, FACTOR, 2)]
     ],
     [
        (example.py, [(1, LEARNING_RATE, 0.3), (2, DECAY, 0.2)]),
        (example_2.py, [(1, FACTOR, 2)]
     ]
    ]

    """
    list_all_strategies = []

    dict_idx_to_file = {}
    dict_idx_to_line_number = {}
    dict_idx_to_var_name = {}

    # File name => list of edit instructions
    dict_file_to_edit_instructions = {}

    list_args_for_product = []
    running_idx = 0
    for dict_config in configs:
        path = dict_config['path']
        dict_file_to_edit_instructions[path] = []
        for config in dict_config['configurations']:
            line_number = config['line_number']
            variable = config['variable']
            dict_idx_to_file[running_idx] = path
            dict_idx_to_line_number[running_idx] = line_number
            dict_idx_to_var_name[running_idx] = variable
            values = config['value']
            if type(values) is list:
                list_args_for_product.append(values)
            else:
                list_args_for_product.append([values])
            running_idx += 1

    list_all_products = list(itertools.product(*list_args_for_product))
    for list_strategy_values in list_all_products:
        dict_file_to_edit_instructions_copy = copy.deepcopy(dict_file_to_edit_instructions)
        for value_idx, value in enumerate(list_strategy_values):
            path = dict_idx_to_file[value_idx]
            line_number = dict_idx_to_line_number[value_idx]
            var_name = dict_idx_to_var_name[value_idx]
            dict_file_to_edit_instructions_copy[path].append((line_number, var_name, value))

        list_all_strategies.append(list(dict_file_to_edit_instructions_copy.items()))

    return list_all_strategies