from typing import Dict
from typing import Any
import re


def deepdiff_path_to_openmm_path(
    openmm_system: Dict[str, Any], deepdiff_path: str, index_to_wildcard: bool = True
):
    """Converts a 'path' to the attribute in an object generated by DeepDiff to a more
    readable and comprehensible 'path' to a field in an XML serialized OpenMM system.

    For example:

    * ``"root['Particles'][i]['mass']"``    -> "Particles/*/mass"
    * ``"root['Forces'][i]['Bonds'][j]['k'] -> "Forces/HarmonicBondForce/Bonds/*/k"
    * ``"root['Forces'][i]['cutoff']        -> "Forces/NonbondedForce/cutoff"
    * ``"root['Forces'][i]['Particles'][j]  >  "Forces/NonbondedForce/Particles/*"
    """

    assert deepdiff_path.startswith("root")

    openmm_path = deepdiff_path[5:].replace("][", "/").replace("'", "").rstrip("]")

    if openmm_path.startswith("Forces"):

        force_matches = re.findall(r"Forces/(\d+?)/", openmm_path)
        assert len(force_matches) == 1

        [force_match] = force_matches

        force_index = int(force_match)
        force_type = openmm_system["Forces"][force_index]["type"]

        openmm_path = openmm_path.replace(
            f"Forces/{force_index}/", f"Forces/{force_type}/"
        )

    if index_to_wildcard:
        openmm_path = re.sub(r"/\d+?/", "/*/", openmm_path)

    return openmm_path