import copy


def _enforce_hierarchy(dupe_dict, values, hierarchy):
    """ Enforce a general hierarchy of which structures to keep, based
    on the list of values and their importance.

    Parameters:
        dupe_dict (dict): the dictionary keyed by the index of unique structures
            that holds lists of duplicates for that structure.
        values (list): the list of values for each structure on which to enforce
            the hierarchy.
        hierarchy (list): the order in which to consider the values, e.g.
            `['ICSD', 'OQMD']` will promote ICSD structures over OQMD.

    Returns:
        dict: the reshuffled dictionary of duplicates.

    """
    max_val = max(list(dupe_dict.keys()) + [val for t in dupe_dict.values() for val in t])

    if len(values) - 1 != max_val:
        raise RuntimeError("Number of hierarchy values does not much number of items: {} vs {}"
                           .format(len(values)-1, max_val))

    new_dupe_dict = copy.deepcopy(dupe_dict)

    swapped = []
    for i in new_dupe_dict:
        if not list(new_dupe_dict[i]):
            continue
        for value in hierarchy:
            found = False
            for k in [i] + list(new_dupe_dict[i]):
                if values[k] == value:
                    swapped.append((i, k))
                    found = True
                    break
            if found:
                break

    for i, k in swapped:
        if i != k:
            if k in new_dupe_dict:
                new_dupe_dict[k].update([ind for ind in new_dupe_dict[i] if ind != k] + [i])
            else:
                new_dupe_dict[k] = set([ind for ind in new_dupe_dict[i] if ind != k] + [i])
            del new_dupe_dict[i]

    return new_dupe_dict