/**
 * Oracle memory report — SGA treemap (d3) + PGA bar chart (Observable Plot).
 * Reads data from window.DemoOracleReport.memory.
 */
(function () {
'use strict';

var cfg            = (window.DemoOracleReport && window.DemoOracleReport.memory) || {};
var sgaRows        = cfg.sgaRows        || [];
var pgaChartLabels = cfg.pgaChartLabels || {};
var pgaChartValues = cfg.pgaChartValues || {};

/* ── Helpers ─────────────────────────────────────────────── */
function fmtBytes(b) {
    b = +b;
    if (!b || b <= 0) return '0 B';
    if (b >= 1073741824) return (b / 1073741824).toFixed(2) + ' GB';
    if (b >= 1048576)    return (b / 1048576).toFixed(1) + ' MB';
    if (b >= 1024)       return (b / 1024).toFixed(1) + ' KB';
    return b + ' B';
}

function themeVar(v, fallback) {
    var val = getComputedStyle(document.documentElement).getPropertyValue(v).trim();
    return val || fallback;
}

/* ══════════════════════════════════════════════════════════
   SGA TREEMAP — d3.treemap()
══════════════════════════════════════════════════════════ */

var SGA_COLORS = {
    'Buffer Cache Size':           '#3b82f6',
    'Default Buffer Cache Size':   '#3b82f6',
    'Db Cache Size':               '#3b82f6',
    'Shared Pool Size':            '#8b5cf6',
    'Large Pool Size':             '#06b6d4',
    'Java Pool Size':              '#f59e0b',
    'Streams Pool Size':           '#10b981',
    'Shared IO Pool Size':         '#f97316',
    'In-Memory Area Size':         '#ec4899',
    'Fixed SGA Size':              '#64748b',
    'Redo Buffers':                '#84cc16',
    'Free SGA Memory Available':   '#cbd5e1',
    'Startup overhead in Shared Pool': '#a78bfa',
};

function sgaColor(name) {
    return SGA_COLORS[name] || '#6366f1';
}

function renderSGATreemap() {
    var container = document.getElementById('chart-sga-treemap');
    if (!container || !sgaRows.length || typeof d3 === 'undefined') return;

    var W = container.clientWidth || 800;
    var H = Math.max(300, Math.round(W * 0.46));

    var root = d3.hierarchy({ name: 'SGA', children: sgaRows })
        .sum(function (d) { return d.bytes || 0; })
        .sort(function (a, b) { return b.value - a.value; });

    d3.treemap()
        .size([W, H])
        .paddingOuter(3)
        .paddingInner(2)
        .round(true)(root);

    var svg = d3.create('svg')
        .attr('viewBox', '0 0 ' + W + ' ' + H)
        .attr('width', '100%')
        .style('display', 'block')
        .style('overflow', 'visible');

    var leaf = svg.selectAll('g.leaf')
        .data(root.leaves())
        .join('g')
        .attr('class', 'leaf')
        .attr('transform', function (d) { return 'translate(' + d.x0 + ',' + d.y0 + ')'; });

    /* Tooltip */
    leaf.append('title').text(function (d) {
        return d.data.name + '\n' + fmtBytes(d.data.bytes) +
               (d.data.resizeable === 'Yes' ? '\n(redimensionnable)' : '');
    });

    /* Rectangle */
    leaf.append('rect')
        .attr('width',  function (d) { return Math.max(0, d.x1 - d.x0); })
        .attr('height', function (d) { return Math.max(0, d.y1 - d.y0); })
        .attr('fill',   function (d) { return sgaColor(d.data.name); })
        .attr('stroke', themeVar('--color-bg', '#fff'))
        .attr('stroke-width', 1.5)
        .attr('rx', 4);

    /* Labels — only when the rect is large enough */
    leaf.each(function (d) {
        var w = d.x1 - d.x0;
        var h = d.y1 - d.y0;
        if (w < 55 || h < 22) return;

        var isFree = (d.data.name === 'Free SGA Memory Available');
        var textFill = isFree ? '#475569' : 'white';
        var g = d3.select(this);

        var clipId = 'c' + Math.random().toString(36).slice(2);
        g.append('clipPath').attr('id', clipId)
            .append('rect')
            .attr('x', 4).attr('y', 4)
            .attr('width', Math.max(0, w - 8))
            .attr('height', Math.max(0, h - 8));

        var showSize = h > 44;
        var cy = showSize ? h / 2 - 7 : h / 2 + 4;
        var fs = Math.min(12, Math.max(9, w / 9));

        var t = g.append('text')
            .attr('clip-path', 'url(#' + clipId + ')')
            .attr('fill', textFill)
            .attr('font-weight', '600')
            .attr('font-size', fs);

        t.append('tspan')
            .attr('x', w / 2).attr('y', cy)
            .attr('text-anchor', 'middle')
            .text(d.data.name);

        if (showSize) {
            t.append('tspan')
                .attr('x', w / 2).attr('y', h / 2 + 9)
                .attr('text-anchor', 'middle')
                .attr('font-size', Math.min(11, Math.max(8, fs - 1)))
                .attr('font-weight', 'normal')
                .attr('opacity', 0.88)
                .text(fmtBytes(d.data.bytes));
        }
    });

    container.innerHTML = '';
    container.appendChild(svg.node());
}

/* ══════════════════════════════════════════════════════════
   PGA CHART — Observable Plot horizontal bars
══════════════════════════════════════════════════════════ */

function renderPGAChart() {
    var container = document.getElementById('chart-pga');
    if (!container || typeof Plot === 'undefined') return;

    /* Build dataset: only rows with value > 0 */
    var rows = [
        { label: pgaChartLabels.target    || 'PGA Target',    value: pgaChartValues.target    || 0, color: '#94a3b8' },
        { label: pgaChartLabels.max       || 'Max Allocated',  value: pgaChartValues.maxAlloc  || 0, color: '#f97316' },
        { label: pgaChartLabels.allocated || 'Allocated',      value: pgaChartValues.allocated || 0, color: '#3b82f6' },
        { label: pgaChartLabels.inuse     || 'In Use',         value: pgaChartValues.inuse     || 0, color: '#ef4444' },
        { label: pgaChartLabels.freeable  || 'Freeable',       value: pgaChartValues.freeable  || 0, color: '#22c55e' },
    ].filter(function (d) { return d.value > 0; });

    if (!rows.length) return;

    var w = container.clientWidth || 600;

    var plot = Plot.plot({
        width: w,
        height: rows.length * 52 + 44,
        marginLeft: 220,
        marginRight: 110,
        x: { label: null, tickFormat: fmtBytes, nice: true },
        y: { label: null, tickSize: 0, domain: rows.map(function (d) { return d.label; }) },
        marks: [
            Plot.barX(rows, {
                x: 'value',
                y: 'label',
                fill: 'color',
                rx: 4,
                title: function (d) { return d.label + '\n' + fmtBytes(d.value); },
            }),
            /* Value label to the right of bar */
            Plot.text(rows, {
                x: 'value',
                y: 'label',
                text: function (d) { return fmtBytes(d.value); },
                dx: 8,
                fill: themeVar('--color-text', '#333'),
                fontSize: 12,
                textAnchor: 'start',
            }),
            Plot.ruleX([0]),
        ],
    });

    container.replaceChildren(plot);
}

/* ── Initial render ─────────────────────────────────────── */
renderSGATreemap();
renderPGAChart();

/* Re-render treemap on resize (debounced) */
var _resizeTimer;
window.addEventListener('resize', function () {
    clearTimeout(_resizeTimer);
    _resizeTimer = setTimeout(renderSGATreemap, 200);
});

})();
