const highlightLinks = new Set();
const highlightNodes = new Set();
let hoverNode = null;

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; 

        // // 特定のノード名の色を変更
        // if (node.id === '農林漁業') {
        //     sprite.color = 'red'; // 特定ノードのテキスト色を赤に変更
        // } else {
        //     sprite.color = node.color; // 他のノードは元の色を使用
        // }

        sprite.textHeight = 7.5;
        return sprite;
    })

    .onEngineStop(() => {
        // ランク付けを実行
        rankNodesByIncomingLinks();
    })
    
    .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>Outgoing Links</h4>`;
        displayArea.innerHTML += `<h4>供給先</h4>`;
        outgoingLinks.forEach(link => {
            displayArea.innerHTML += `<p>${link.target.id} (Value: ${link.value.toFixed(2)})</p>`;
        });

        // 向かってくるリンク
        //displayArea.innerHTML += `<h4>Incoming Links</h4>`;
        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)
    //.linkDirectionalParticleWidth(2)
    //.linkDirectionalParticles("value")
    //.linkDirectionalParticleSpeed(d => d.value * 0.01)
    .linkThreeObjectExtend(true)
    .linkColor(() => 'red') // リンクの色を黒に設定


    .linkWidth(1)
    .backgroundColor("#f8f8f8");

    

// ノード間の力学的レイアウトを調整
Graph
    .d3Force("link").distance(300) // リンクの長さを100に設定（デフォルトは約30-50）
    .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 rankNodesByIncomingLinks() {
    const graphData = Graph.graphData();
    const incomingLinksCount = {};

    // 入力リンクの数を計算
    graphData.nodes.forEach(node => {
        incomingLinksCount[node.id] = 0;
    });
    graphData.links.forEach(link => {
        if (link.target && link.target.id) {
            incomingLinksCount[link.target.id]++;
        }
    });

    // ランク付け
    const rankedNodes = Object.entries(incomingLinksCount)
        .sort((a, b) => a[1] - b[1]) // 入力リンクの数で昇順ソート
        .map(([id, count], index) => ({
            rank: index + 1,
            id: id,
            count: count
        }));

    // 表を作成して表示
    displayRankTable(rankedNodes);
}


// // ノードを出力リンクの数でランク付け
// function rankNodesByOutgoingLinks() {
//     const graphData = Graph.graphData();
//     const outgoingLinksCount = {};

//     // 出力リンクの数を計算
//     graphData.nodes.forEach(node => {
//         outgoingLinksCount[node.id] = 0;
//     });
//     graphData.links.forEach(link => {
//         if (link.source && link.source.id) {
//             outgoingLinksCount[link.source.id]++;
//         }
//     });

//     // ランク付け
//     const rankedNodes = Object.entries(outgoingLinksCount)
//         .sort((a, b) => b[1] - a[1]) // 出力リンクの数で降順ソート
//         .map(([id, count], index) => ({
//             rank: index + 1,
//             id: id,
//             count: count
//         }));

//     // 表を作成して表示
//     displayRankTable(rankedNodes);
// }




// ランク表を表示
function displayRankTable(rankedNodes) {
    const tableContainer = document.getElementById("rankTable");
    if (!tableContainer) {
        console.error("rankTable のコンテナが見つかりません");
        return;
    }

    // 表を作成
    let tableHTML = `
        <table border="1">
            <thead>
                <tr>
                    <th>順位</th>
                    <th>ノード名</th>
                    <th>入力リンク数</th>
                </tr>
            </thead>
            <tbody>
    `;
    rankedNodes.forEach(node => {
        tableHTML += `
            <tr>
                <td>${node.rank}</td>
                <td>${node.id}</td>
                <td>${node.count}</td>
            </tr>
        `;
    });
    tableHTML += `</tbody></table>`;

    // 表をコンテナに追加
    tableContainer.innerHTML = tableHTML;
}