

const Graph = ForceGraph3D()
    (document.getElementById("three"))
    .jsonUrl('http://127.0.0.1:5000/static/json/output_toda_kihon_zenbu.json')
    .nodeColor('#ffffff')
    .nodeLabel('id')
    .nodeRelSize(20)
    .nodeThreeObject(node => {
        const sprite = new SpriteText(node.id);
        sprite.material.depthWrite = false; // make sprite background transparent
        sprite.color = node.color;
        sprite.textHeight = 7.5;
        return sprite;
    })

    .linkThreeObject(link => {
        // extend link with text sprite
        const sprite = new SpriteText(link.value.toFixed(2)); // 小数点1桁にフォーマット
        sprite.color = 'blue';
        sprite.textHeight = 4.0;
        return sprite;
    })
    .linkPositionUpdate((sprite, { start, end }) => {
        const middlePos = Object.assign(...['x', 'y', 'z'].map(c => ({
            [c]: start[c] + (end[c] - start[c]) / 2 // calc middle point
        })));

        // Position sprite
        Object.assign(sprite.position, middlePos);
    })

    .onNodeClick(node => {
        // ノードクリック時に入出力リンクを表示
        const outgoingLinks = Graph.graphData().links.filter(link => link.source.id === node.id);
        const incomingLinks = Graph.graphData().links.filter(link => link.target.id === node.id);

        // 左上に情報を表示
        const displayArea = document.getElementById("info");
        displayArea.innerHTML = `<h3>Node: ${node.id}</h3>`;
        
        // 出ているリンク
        displayArea.innerHTML += `<h4>供給先</h4>`;
        outgoingLinks.forEach(link => {
            displayArea.innerHTML += `<p>${link.target.id} (Value: ${link.value.toFixed(2)})</p>`;
        });

        // 向かってくるリンク
        displayArea.innerHTML += `<h4>投入先</h4>`;
        incomingLinks.forEach(link => {
            displayArea.innerHTML += `<p>${link.source.id} (Value: ${link.value.toFixed(2)})</p>`;
        });
    })

    .onNodeHover(node => {
        // ノードにホバーした時の処理
        hoverNode = node ? node.id : null;
        updateHoverText(); // テキストを更新する関数を呼び出す
    })
    .linkOpacity(0.25)
    .linkDirectionalArrowLength(3)
    .linkDirectionalArrowRelPos(1)
    .linkCurvature(0.01)
    .linkThreeObjectExtend(true)
    .linkColor(() => 'red') // リンクの色を赤に設定
    .linkWidth(1)
    .backgroundColor("#f8f8f8");

// ノード間の力学的レイアウトを調整
Graph
    .d3Force("link").distance(300) // リンクの長さを設定
    .d3Force("charge").strength(300); // ノード間の反発力を調整


function updateHoverText() {
    // ホバー時のノードのテキストサイズを変更
    Graph.nodeThreeObject(node => {
        const sprite = new SpriteText(node.id);
        sprite.material.depthWrite = false;
        sprite.color = node.color;
        sprite.textHeight = hoverNode === node.id ? 15 : 7.5; // ホバー時にテキストサイズを変更
        return sprite;
    });
}

// ランク表の作成関数
function createRankTable() {
    const graphData = Graph.graphData();

    const nodeRank = {};

    // 各ノードの出ていくリンク数をカウント
    graphData.links.forEach(link => {
        const sourceId = link.source.id;
        nodeRank[sourceId] = (nodeRank[sourceId] || 0) + 1;
    });

    // ランク付けのためソート
    const sortedNodes = Object.entries(nodeRank)
        .sort((a, b) => b[1] - a[1]); // 出ていくリンク数が多い順にソート

    // ランク表を表示
    const rankDisplayArea = document.getElementById("rank");
    rankDisplayArea.innerHTML = "<h3>ランク表</h3>";
    sortedNodes.forEach(([nodeId, count], index) => {
        rankDisplayArea.innerHTML += `<p>${index + 1}. ${nodeId} (Outgoing Links: ${count})</p>`;
    });
}

Graph.onLoadingFinished(() => {
    console.log("グラフデータが読み込まれました:", Graph.graphData());
    createRankTable();
});
