import re

try:
    from jsonpath_ng import parse as jsonpath
    jsonpath_installed = True
except ImportError:
    jsonpath_installed = False

from six.moves import zip_longest


empty = object()


def obj_merge(a, b):
    c = {}
    for k, v in a.items():
        if k not in b:
            c[k] = v
        else:
            c[k] = obj_check(v, b[k])
    for k, v in b.items():
        if k not in a:
            c[k] = v
    return c


def obj_check(a, b):
    c = None
    if not isinstance(a, type(b)):
        c = a
    else:
        if isinstance(a, dict):
            c = obj_merge(a, b)
        elif isinstance(a, list):
            z = []
            for x, y in zip_longest(a, b, fillvalue=empty):
                if x is empty:
                    z.append(y)
                elif y is empty:
                    z.append(x)
                else:
                    z.append(obj_check(x, y))
            c = z
        else:
            c = a
    return c


def jsonpath_parse(template, obj):
    def repl(m):
        path = m.group(2)
        if not path.startswith("$"):
            path = "$" + path
        return jsonpath(path).find(obj)[0].value
    return re.sub(r"(\{([^\}]*)\})", repl, template)