# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

import subprocess
from os import path

from mozfile import json

from qm_try_analysis.logging import info, warning

cached_functions = {}


def getMetricsJson(src_url):
    if src_url.startswith("http"):
        info(f"Fetching source for function extraction: {src_url}")
        metrics = subprocess.check_output([
            path.join(path.dirname(path.realpath(__file__)), "fetch_fn_names.sh"),
            src_url,
        ])
    else:
        warning(f"Skip fetching source: {src_url}")
        metrics = ""

    try:
        return json.loads(metrics)
    except ValueError:
        return {"kind": "empty", "name": "anonymous", "spaces": []}


def getSpaceFunctionsRecursive(metrics_space):
    functions = []
    if (
        metrics_space["kind"] == "function"
        and metrics_space["name"]
        and metrics_space["name"] != "<anonymous>"
    ):
        functions.append({
            "name": metrics_space["name"],
            "start_line": int(metrics_space["start_line"]),
            "end_line": int(metrics_space["end_line"]),
        })
    for space in metrics_space["spaces"]:
        functions += getSpaceFunctionsRecursive(space)
    return functions


def getSourceFunctions(src_url):
    if src_url not in cached_functions:
        metrics_space = getMetricsJson(src_url)
        cached_functions[src_url] = getSpaceFunctionsRecursive(metrics_space)

    return cached_functions[src_url]


def getFunctionName(location):
    location.replace("annotate", "raw-file")
    pieces = location.split("#l")
    src_url = pieces[0]
    line = int(pieces[1])
    closest_name = f"<Unknown {line}>"
    closest_start = 0
    functions = getSourceFunctions(src_url)
    for fn in functions:
        if (
            fn["start_line"] > closest_start
            and line >= fn["start_line"]
            and line <= fn["end_line"]
        ):
            closest_start = fn["start_line"]
            closest_name = fn["name"]
    return closest_name
