"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const genutils_1 = require("./genutils");
const svparser_1 = require("./svparser");
const child = require("child_process");
let index_file = process.argv[2];
let moduleMap = new Map();
let interfaceMap = new Map();
let pkgMap = new Map();
let depsInfo = new Map();
function process_container_maps(file_path, containerInfo) {
    if ((containerInfo.length > svparser_1.SystemVerilogParser.ContainerInfoIndex.Containers) &&
        (containerInfo[svparser_1.SystemVerilogParser.ContainerInfoIndex.Containers] != undefined)) {
        for (let childContainerInfo of (containerInfo[svparser_1.SystemVerilogParser.ContainerInfoIndex.Containers])) {
            let symbol = childContainerInfo[0][0];
            if (symbol.type[0] == "module") {
                moduleMap.set(symbol.name, file_path);
            }
            else if (symbol.type[0] == "interface") {
                interfaceMap.set(symbol.name, file_path);
            }
            else if (symbol.type[0] == "package") {
                pkgMap.set(symbol.name, file_path);
            }
            let containerSymbolsInfo = childContainerInfo[1];
            process_container_maps(file_path, containerSymbolsInfo);
        }
    }
}
function process_file_maps(file_path, file_symbols_info) {
    if ((file_symbols_info.length > svparser_1.SystemVerilogParser.FileInfoIndex.Containers) &&
        (file_symbols_info[svparser_1.SystemVerilogParser.FileInfoIndex.Containers] != undefined)) {
        for (let containerInfo of (file_symbols_info[svparser_1.SystemVerilogParser.FileInfoIndex.Containers])) {
            let symbol = containerInfo[0][0];
            if (symbol.type[0] == "module") {
                moduleMap.set(symbol.name, file_path);
            }
            else if (symbol.type[0] == "interface") {
                interfaceMap.set(symbol.name, file_path);
            }
            else if (symbol.type[0] == "package") {
                pkgMap.set(symbol.name, file_path);
            }
            let containerSymbolsInfo = containerInfo[1];
            process_container_maps(file_path, containerSymbolsInfo);
        }
    }
}
function process_container_info(file_path, containerInfo) {
    let result = { moduleDeps: [], interfaceDeps: [], pkgDeps: [], includes: [] };
    if ((containerInfo.length > svparser_1.SystemVerilogParser.ContainerInfoIndex.Symbols) &&
        (containerInfo[svparser_1.SystemVerilogParser.ContainerInfoIndex.Symbols] != undefined)) {
        for (let symbol of (containerInfo[svparser_1.SystemVerilogParser.ContainerInfoIndex.Symbols])) {
            if (symbol.type[0] == "instance") {
                if (moduleMap.has(symbol.type[1])) {
                    result.moduleDeps.push(moduleMap.get(symbol.type[1]));
                }
                else if (interfaceMap.has(symbol.type[1])) {
                    result.interfaceDeps.push(interfaceMap.get(symbol.type[1]));
                }
                else if (pkgMap.has(symbol.type[1])) {
                    result.pkgDeps.push(pkgMap.get(symbol.type[1]));
                }
            }
        }
    }
    //if ((containerInfo.length > SystemVerilogParser.ContainerInfoIndex.Imports) &&
    //    (containerInfo[SystemVerilogParser.ContainerInfoIndex.Imports] != undefined)) {
    //    for (let importItem of <SystemVerilogParser.SystemVerilogImportsInfo>(containerInfo[SystemVerilogParser.ContainerInfoIndex.Imports])) {
    //        console.log(`DEBUG: imports from "${importItem[0]}" are ${importItem[1]}`);
    //    }
    //}
    if ((containerInfo.length > svparser_1.SystemVerilogParser.ContainerInfoIndex.Containers) &&
        (containerInfo[svparser_1.SystemVerilogParser.ContainerInfoIndex.Containers] != undefined)) {
        for (let childContainerInfo of (containerInfo[svparser_1.SystemVerilogParser.ContainerInfoIndex.Containers])) {
            let containerSymbolsInfo = childContainerInfo[1];
            let container_result = process_container_info(file_path, containerSymbolsInfo);
            result.moduleDeps = result.moduleDeps.concat(container_result.moduleDeps);
            result.interfaceDeps = result.interfaceDeps.concat(container_result.interfaceDeps);
            result.pkgDeps = result.pkgDeps.concat(container_result.pkgDeps);
            result.includes = result.includes.concat(container_result.includes);
        }
    }
    //if ((containerInfo.length > SystemVerilogParser.ContainerInfoIndex.Exports) &&
    //    (containerInfo[SystemVerilogParser.ContainerInfoIndex.Exports] != undefined)) {
    //    for (let exportItem of <SystemVerilogParser.SystemVerilogExportsInfo>(containerInfo[SystemVerilogParser.ContainerInfoIndex.Exports])) {
    //        console.log(`DEBUG: exports from "${exportItem[0]}" are ${exportItem[1]}`);
    //    }
    //}
    return result;
}
function process_file_symbols_info(file_path, file_symbols_info) {
    let result = { moduleDeps: [], interfaceDeps: [], pkgDeps: [], includes: [] };
    if ((file_symbols_info.length > svparser_1.SystemVerilogParser.FileInfoIndex.Containers) &&
        (file_symbols_info[svparser_1.SystemVerilogParser.FileInfoIndex.Containers] != undefined)) {
        for (let containerInfo of (file_symbols_info[svparser_1.SystemVerilogParser.FileInfoIndex.Containers])) {
            let containerSymbolsInfo = containerInfo[1];
            let container_result = process_container_info(file_path, containerSymbolsInfo);
            result.moduleDeps = result.moduleDeps.concat(container_result.moduleDeps);
            result.interfaceDeps = result.interfaceDeps.concat(container_result.interfaceDeps);
            result.pkgDeps = result.pkgDeps.concat(container_result.pkgDeps);
            result.includes = result.includes.concat(container_result.includes);
        }
    }
    if ((file_symbols_info.length > svparser_1.SystemVerilogParser.FileInfoIndex.Includes) &&
        (file_symbols_info[svparser_1.SystemVerilogParser.FileInfoIndex.Includes] != undefined) &&
        (file_symbols_info[svparser_1.SystemVerilogParser.FileInfoIndex.Includes].length > 0)) {
        result.includes = result.includes.concat((file_symbols_info[svparser_1.SystemVerilogParser.FileInfoIndex.Includes]));
    }
    //if ((file_symbols_info.length > SystemVerilogParser.FileInfoIndex.Imports) &&
    //    (file_symbols_info[SystemVerilogParser.FileInfoIndex.Imports] != undefined) &&
    //    (file_symbols_info[SystemVerilogParser.FileInfoIndex.Imports].length > 0)) {
    //    for (let importItem of <SystemVerilogParser.SystemVerilogImportsInfo>(file_symbols_info[SystemVerilogParser.ContainerInfoIndex.Imports])) {
    //        console.log(`DEBUG: global imports from "${importItem[0]}" are ${importItem[1]}`);
    //    }
    //}
    //if ((file_symbols_info.length > SystemVerilogParser.FileInfoIndex.Exports) &&
    //    (file_symbols_info[SystemVerilogParser.FileInfoIndex.Exports] != undefined) &&
    //    (file_symbols_info[SystemVerilogParser.FileInfoIndex.Exports].length > 0)) {
    //    for (let exportItem of <SystemVerilogParser.SystemVerilogExportsInfo>(file_symbols_info[SystemVerilogParser.ContainerInfoIndex.Exports])) {
    //        console.log(`DEBUG: global exports from "${exportItem[0]}" are ${exportItem[1]}`);
    //    }
    //}
    //if ((file_symbols_info.length > SystemVerilogParser.FileInfoIndex.Symbols) &&
    //    (file_symbols_info[SystemVerilogParser.FileInfoIndex.Symbols] != undefined)) {
    //    for (let symbol of <SystemVerilogParser.SystemVerilogSymbolsInfo>(file_symbols_info[SystemVerilogParser.FileInfoIndex.Symbols])) {
    //        console.log(`DEBUG: symbol "${symbol.name}" of type ${symbol.type}`);
    //    }
    //}
    depsInfo.set(file_path, result);
}
function process_pkg_deps(file_path_map) {
    child.exec("cd /home/user/git/fpga && grep -R -o '[a-zA-Z0-9_]\\+::' --include='*.sv' --include='*.svh' --include='*.v' --include='*.vh' --exclude-dir='bazel-fpga' | sort -u", { maxBuffer: 8 * 1024 * 1024 }, (err, stdout, stderr) => {
        for (let line of stdout.split(/\r?\n/)) {
            if (!line.endsWith('::')) {
                continue;
            }
            let [short_file_path, pkg_name] = line.split(/:/);
            if (short_file_path.startsWith("bazel-out/k8-dbg-gccdebug/")) {
                short_file_path = "bazel-" + short_file_path.substring("bazel-out/k8-dbg-gccdebug/".length);
            }
            if (depsInfo.has(short_file_path) && pkgMap.has(pkg_name)) {
                depsInfo.get(short_file_path).pkgDeps.push(pkgMap.get(pkg_name));
            }
        }
        console.log(`${JSON.stringify(Object.fromEntries(depsInfo), null, 2)}`);
    });
    //for (let [short_file_path, file_path] of file_path_map.entries()) {
    //    const proc = child.spawn('sh', ["-c", `grep -o '[^ ]\\+::' ${file_path} | sort -u`]);
    //    proc.stdout.on('data', (data) => {
    //        for (let pkg of data.toString().split(/\r?\n/)) {
    //            if (!pkg.endsWith('::')) {
    //                continue;
    //            }
    //            let pkg_name: string = pkg.substring(0, pkg.length - 2);
    //            if (pkgMap.has(pkg_name)) {
    //                depsInfo.get(short_file_path).pkgDeps.push(pkgMap.get(pkg_name));
    //            }
    //            pkg_proc_done();
    //        }
    //    });
    //}
}
function process_index(json_data) {
    let file_path_map = new Map();
    let trim_file_path = (file_path) => {
        let result;
        if (file_path.startsWith("/home/user/git/fpga/")) {
            result = file_path.substring("/home/user/git/fpga/".length);
        }
        else if (file_path.startsWith("/home/user/.cache/bazel/_bazel_kkanhere/45a25349d964d9277de9ddc3d9c29744/execroot/falcon/bazel-out/k8-dbg-gccdebug/")) {
            result = "bazel-" + file_path.substring("/home/user/.cache/bazel/_bazel_kkanhere/45a25349d964d9277de9ddc3d9c29744/execroot/falcon/bazel-out/k8-dbg-gccdebug/".length);
        }
        else if (file_path.startsWith("/home/user/.cache/bazel/_bazel_kkanhere/45a25349d964d9277de9ddc3d9c29744/external/")) {
            result = "bazel-" + file_path.substring("/home/user/.cache/bazel/_bazel_kkanhere/45a25349d964d9277de9ddc3d9c29744/external/".length);
        }
        else {
            result = file_path;
        }
        file_path_map.set(result, file_path);
        return result;
    };
    let files_info = new Map(json_data.info.map(info => [
        trim_file_path(info[0]),
        ({
            symbolsInfo: svparser_1.SystemVerilogParser.jsonToFileSymbolsInfo(info[0], info[1][0]),
            pkgdeps: info[1][1],
            rank: info[1][2]
        })
    ]));
    for (let [file_path, file_info] of files_info.entries()) {
        process_file_maps(file_path, file_info.symbolsInfo);
    }
    for (let [file_path, file_info] of files_info.entries()) {
        process_file_symbols_info(file_path, file_info.symbolsInfo);
    }
    process_pkg_deps(file_path_map);
    //console.log(`${JSON.stringify(Object.fromEntries(depsInfo), null, 2)}`);
}
genutils_1.fsExists(index_file)
    .then(() => {
    return genutils_1.fsReadFile(index_file);
})
    .then((data) => {
    process_index(JSON.parse(data));
    //let dbg_map: Map<string, string> = new Map();
    //dbg_map.set("hw/building_blocks/i2c_wrapper.sv", "/home/user/git/fpga/hw/building_blocks/i2c_wrapper.sv");
    //process_pkg_deps(dbg_map);
})
    .catch((error) => {
    console.error("Couldn't read or process index file");
});
