<?php

require_once "../common/db.php";

$xmlPath = __DIR__ . "/../DataSource/mainContent.xml";

if (!file_exists($xmlPath)) {
    die("XML non trovato");
}

$xml = simplexml_load_file($xmlPath);

if (!$xml) {
    die("Errore apertura XML");
}

$db->query("SET FOREIGN_KEY_CHECKS=0");

$db->query("TRUNCATE TABLE node_tags");
$db->query("TRUNCATE TABLE tags");
$db->query("TRUNCATE TABLE node_styles");
$db->query("TRUNCATE TABLE nodes");

$db->query("SET FOREIGN_KEY_CHECKS=1");

$xmlToDb = [];
$tagCache = [];

function attr($node, $name)
{
    $attrs = $node->attributes();

    return isset($attrs[$name])
        ? (string)$attrs[$name]
        : null;
}

function getTagId($db, &$tagCache, $name)
{
    $name = trim($name);

    if ($name === "") {
        return null;
    }

    if (isset($tagCache[$name])) {
        return $tagCache[$name];
    }

    $stmt = $db->prepare(
        "INSERT IGNORE INTO tags(name)
         VALUES(?)"
    );

    $stmt->bind_param("s", $name);
    $stmt->execute();

    $stmt = $db->prepare(
        "SELECT id
         FROM tags
         WHERE name=?"
    );

    $stmt->bind_param("s", $name);
    $stmt->execute();

    $res = $stmt->get_result();
    $row = $res->fetch_assoc();

    $tagCache[$name] = $row["id"];

    return $row["id"];
}

function parseAttributeValue($value)
{
    if (!preg_match(
        '/^(.*?)\-(true|false)\-(true|false)\:(\d+)\-(\d+)$/',
        $value,
        $m
    )) {
        return null;
    }

    return [
        "scale" => $m[1] === "nil" ? null : $m[1],
        "bold" => $m[2] === "true",
        "code" => $m[3] === "true",
        "start" => intval($m[4]),
        "length" => intval($m[5])
    ];
}

function parseLink($link)
{
    if (preg_match(
        '/^pentest:\/\/nodelink\/(\d+)RANGE_FOR_PENTEST_APP:(\d+)\-(\d+)$/',
        $link,
        $m
    )) {
        return [
            "type" => "node",
            "nodeId" => intval($m[1]),
            "start" => intval($m[2]),
            "length" => intval($m[3])
        ];
    }

    if (preg_match(
        '/^(.*?)RANGE_FOR_PENTEST_APP:(\d+)\-(\d+)$/',
        $link,
        $m
    )) {
        return [
            "type" => "web",
            "url" => $m[1],
            "start" => intval($m[2]),
            "length" => intval($m[3])
        ];
    }

    return null;
}

function importNode(
    $db,
    $node,
    $parentId,
    $sortOrder,
    &$xmlToDb,
    &$tagCache
)
{
    $title = attr($node, "name") ?? "";
    $xmlId = intval(attr($node, "unique_id"));
    $color = attr($node, "foreground");

    $isBold =
        attr($node, "is_bold") === "true"
            ? 1
            : 0;

    $content = "";

    if (isset($node->attributedString)) {
        $content =
            attr(
                $node->attributedString,
                "string"
            ) ?? "";
    }

    $stmt = $db->prepare(
        "INSERT INTO nodes
        (
            parent_id,
            old_xml_id,
            sort_order,
            title,
            content,
            color,
            is_bold
        )
        VALUES
        (
            ?,?,?,?,?,?,?
        )"
    );

    $stmt->bind_param(
        "iiisssi",
        $parentId,
        $xmlId,
        $sortOrder,
        $title,
        $content,
        $color,
        $isBold
    );

    $stmt->execute();

    $nodeId = $stmt->insert_id;

    $xmlToDb[$xmlId] = $nodeId;

    $tagsString = attr($node, "tagsString");

    if ($tagsString) {

        $tags =
            array_filter(
                array_map(
                    "trim",
                    explode("-", $tagsString)
                )
            );

        foreach ($tags as $tagName) {

            $tagId =
                getTagId(
                    $db,
                    $tagCache,
                    $tagName
                );

            $stmt =
                $db->prepare(
                    "INSERT IGNORE INTO node_tags
                    (
                        node_id,
                        tag_id
                    )
                    VALUES
                    (?,?)"
                );

            $stmt->bind_param(
                "ii",
                $nodeId,
                $tagId
            );

            $stmt->execute();
        }
    }

    if (isset($node->attributedString)) {

        $links = [];

        foreach (
            $node->attributedString->attribute
            as $attribute
        ) {

            $link =
                attr(
                    $attribute,
                    "link"
                );

            if (!$link) {
                continue;
            }

            $parsed =
                parseLink($link);

            if (!$parsed) {
                continue;
            }

            $key =
                $parsed["start"]
                . "-"
                . $parsed["length"];

            $links[$key] = $parsed;
        }

        foreach (
            $node->attributedString->attribute
            as $attribute
        ) {

            $value =
                attr(
                    $attribute,
                    "value"
                );

            if (!$value) {
                continue;
            }

            $parsed =
                parseAttributeValue(
                    $value
                );

            if (!$parsed) {
                continue;
            }

            $key =
                $parsed["start"]
                . "-"
                . $parsed["length"];

            $webLink = null;
            $oldNodeLink = null;

            if (isset($links[$key])) {

                if (
                    $links[$key]["type"]
                    === "web"
                ) {
                    $webLink =
                        $links[$key]["url"];
                }

                if (
                    $links[$key]["type"]
                    === "node"
                ) {
                    $oldNodeLink =
                        $links[$key]["nodeId"];
                }
            }

            $stmt =
                $db->prepare(
                    "INSERT INTO node_styles
                    (
                        node_id,
                        start_pos,
                        length,
                        scale,
                        is_bold,
                        is_code,
                        web_link,
                        old_node_link
                    )
                    VALUES
                    (
                        ?,?,?,?,?,?,?,?
                    )"
                );

            $bold =
                $parsed["bold"] ? 1 : 0;

            $code =
                $parsed["code"] ? 1 : 0;

            $stmt->bind_param(
                "iiisiisi",
                $nodeId,
                $parsed["start"],
                $parsed["length"],
                $parsed["scale"],
                $bold,
                $code,
                $webLink,
                $oldNodeLink
            );

            $stmt->execute();
        }
    }

    $index = 0;

    foreach ($node->node as $child) {

        importNode(
            $db,
            $child,
            $nodeId,
            $index++,
            $xmlToDb,
            $tagCache
        );
    }
}

$index = 0;

foreach ($xml->node as $node) {

    importNode(
        $db,
        $node,
        null,
        $index++,
        $xmlToDb,
        $tagCache
    );
}

echo "Import completato\n";
echo "Nodi: " . count($xmlToDb) . "\n";
echo "Tag: " . count($tagCache) . "\n";
?>
