/**
 * Oracle tablespaces report — chart rendering (Observable Plot).
 * Reads data from window.DemoOracleReport.tablespaces.
 */
/*
 * Portage demo_oracle : le tri du graphique et l'ouverture de la fenetre de
 * redimensionnement ont ete retires. Les boutons de tri restent affiches,
 * desactives, cote template.
 */
(function () {
    'use strict';

    var cfg     = (window.DemoOracleReport && window.DemoOracleReport.tablespaces) || {};
    var tsData  = cfg.tsData  || [];
    var tmpData = cfg.tmpData || [];
    var labels  = cfg.labels  || {};

    // ── Sort state (default: largest first, matching SQL ORDER BY) ────────
    var tsSortKey  = 'total';
    var tmpSortKey = 'total';

    // ── Helpers ───────────────────────────────────────────────────────────
    function fmtBytes(b) {
        if (b >= 1099511627776) return (b / 1099511627776).toFixed(1) + ' To';
        if (b >= 1073741824)    return (b / 1073741824).toFixed(1) + ' Go';
        if (b >= 1048576)       return Math.round(b / 1048576) + ' Mo';
        return b + ' o';
    }

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

    function sortRows(rows, key) {
        var s = rows.slice();
        if (key === 'name') {
            s.sort(function (a, b) { return a.name.localeCompare(b.name); });
        } else if (key === 'total') {
            s.sort(function (a, b) { return b.total - a.total; });
        } else if (key === 'free') {
            s.sort(function (a, b) {
                var fa = a.free != null ? a.free : (a.total - (a.used || 0));
                var fb = b.free != null ? b.free : (b.total - (b.used || 0));
                return fb - fa;
            });
        }
        return s;
    }

    // ── i18n labels ──────────────────────────────────────────────────────
    var usedLabel  = labels.usedLabel  || 'Used';
    var freeLabel  = labels.freeLabel  || 'Free';
    var allocLabel = labels.allocLabel || 'Allocated';

    // ── Build stacked data array ──────────────────────────────────────────
    function toStackData(rows) {
        var out = [];
        rows.forEach(function (d) {
            out.push({ name: d.name, type: usedLabel,
                       bytes: d.used || 0, pct: d.pct });
            out.push({ name: d.name, type: freeLabel,
                       bytes: d.free != null ? d.free : (d.total - (d.used || 0)) });
        });
        return out;
    }

    // ── Post-process: insert total size below each y-axis name ───────────
    function addTotalLabels(container, rows) {
        var totalByName = {};
        var encByName   = {};
        rows.forEach(function (r) {
            totalByName[r.name] = r.total;
            encByName[r.name]   = r.encrypted;
        });
        var textMuted = themeColor('--color-text-muted', '#888');
        container.querySelectorAll('svg text').forEach(function (el) {
            if (el.querySelector('tspan')) return;      // already processed
            var name = el.textContent.trim();
            if (!(name in totalByName)) return;

            // Le module complet rend ici le nom du tablespace cliquable pour
            // les profils DBA : il ouvre la fenetre de redimensionnement.
            // Cette fenetre n'existe pas dans la demonstration, le nom reste
            // donc du texte.

            // Lock icon for encrypted tablespaces
            var FA_LOCK = ' ' + String.fromCharCode(0xf023);  // fa-lock glyph
            if (encByName[name]) {
                var lock = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
                lock.setAttribute('font-family', '"Font Awesome 6 Free"');
                lock.setAttribute('font-weight', '900');
                lock.setAttribute('font-size',   '9');
                lock.setAttribute('fill',        themeColor('--color-primary', '#2563eb'));
                lock.textContent = FA_LOCK;
                el.appendChild(lock);
            }

            var tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
            tspan.setAttribute('x',         el.getAttribute('x') || '0');
            tspan.setAttribute('dy',        '1.0em');
            tspan.setAttribute('font-size', '8');
            tspan.setAttribute('fill',      textMuted);
            tspan.textContent = fmtBytes(totalByName[name]);
            el.appendChild(tspan);
        });
    }

    // Palettes used/free pour différencier visuellement TS (vert) et TEMP (bleu).
    var PALETTE_TS   = ['#4ade80', '#bbf7d0'];
    var PALETTE_TEMP = ['#60a5fa', '#bfdbfe'];

    // ── Render stacked chart ──────────────────────────────────────────────
    function renderStackedChart(container, rows, palette) {
        if (!container || !rows.length) return;
        palette = palette || PALETTE_TS;

        var stackData = toStackData(rows);
        var domain    = rows.map(function (d) { return d.name; });
        var w         = container.clientWidth || 700;
        var h         = rows.length * 27 + 60;
        var textColor = themeColor('--color-text', '#111');
        var totalMax  = Math.max.apply(null, rows.map(function (d) { return d.total; }));
        var minLabel  = totalMax * 0.12;   // masquer l'étiquette si segment < 12 % du max

        var plot = Plot.plot({
            width:       w,
            height:      h,
            marginLeft:  130,
            marginRight: 16,
            style: { fontFamily: 'inherit', fontSize: '11px',
                     background: 'transparent', color: textColor },
            color: {
                legend: true,
                domain: [usedLabel, freeLabel],
                range:  palette
            },
            x: { label: null, tickFormat: fmtBytes, nice: true },
            y: { label: null, tickSize: 0, domain: domain },
            marks: [
                Plot.barX(stackData, Plot.stackX({
                    x:    'bytes',
                    y:    'name',
                    fill: 'type',
                    title: function (d) {
                        var s = d.name + ' — ' + d.type + ' : ' + fmtBytes(d.bytes);
                        if (d.pct != null && d.type === usedLabel) s += ' (' + d.pct + '%)';
                        return s;
                    }
                })),
                Plot.text(stackData, Plot.stackX({
                    x:           'bytes',
                    y:           'name',
                    z:           'type',
                    text: function (d) {
                        if (d.bytes < minLabel) return '';
                        var s = fmtBytes(d.bytes);
                        if (d.pct != null && d.type === usedLabel) s += ' (' + d.pct + '%)';
                        return s;
                    },
                    fill:        'white',
                    stroke:      'rgba(0,0,0,.28)',
                    strokeWidth: 3,
                    paintOrder:  'stroke',
                    fontSize:    9,
                    textAnchor:  'middle'
                })),
                Plot.ruleX([0])
            ]
        });

        container.replaceChildren(plot);
        addTotalLabels(container, rows);
    }

    // ── Draw helpers ──────────────────────────────────────────────────────
    var cTs  = document.getElementById('chart-ts');
    var cTmp = document.getElementById('chart-tmp');
    var hasTmpUsage = tmpData.some(function (d) { return d.used !== null; });

    function drawTs() {
        if (!cTs || !tsData.length) return;
        renderStackedChart(cTs, sortRows(tsData, tsSortKey));
    }

    function drawTmp() {
        if (!cTmp || !tmpData.length) return;
        var sorted = sortRows(tmpData, tmpSortKey);
        if (hasTmpUsage) {
            renderStackedChart(cTmp, sorted, PALETTE_TEMP);
        } else {
            // Pas d'accès à v$temp_space_header : barre simple (taille allouée)
            var domain    = sorted.map(function (d) { return d.name; });
            var allocData = sorted.map(function (d) { return { name: d.name, bytes: d.total }; });
            var totalMax  = Math.max.apply(null, sorted.map(function (d) { return d.total; }));
            var minLabel  = totalMax * 0.08;
            var plot = Plot.plot({
                width:       cTmp.clientWidth || 700,
                height:      sorted.length * 27 + 60,
                marginLeft:  130,
                marginRight: 16,
                style: { fontFamily: 'inherit', fontSize: '11px',
                         background: 'transparent',
                         color: themeColor('--color-text', '#111') },
                color: { legend: true, domain: [allocLabel], range: ['#60a5fa'] },
                x: { label: null, tickFormat: fmtBytes, nice: true },
                y: { label: null, tickSize: 0, domain: domain },
                marks: [
                    Plot.barX(allocData, {
                        x: 'bytes', y: 'name', fill: '#60a5fa',
                        title: function (d) { return d.name + ': ' + fmtBytes(d.bytes); }
                    }),
                    Plot.text(allocData, {
                        x:           function (d) { return d.bytes / 2; },
                        y:           'name',
                        text:        function (d) { return d.bytes >= minLabel ? fmtBytes(d.bytes) : ''; },
                        fill:        'white',
                        stroke:      'rgba(0,0,0,.28)',
                        strokeWidth: 3,
                        paintOrder:  'stroke',
                        fontSize:    9,
                        textAnchor:  'middle'
                    }),
                    Plot.ruleX([0])
                ]
            });
            cTmp.replaceChildren(plot);
            addTotalLabels(cTmp, sorted);
        }
    }

    // ── Initial render ────────────────────────────────────────────────────
    drawTs();
    drawTmp();

    // ── Sort button event handlers ────────────────────────────────────────
    document.querySelectorAll('.btn-sort').forEach(function (btn) {
        btn.addEventListener('click', function () {
            var key    = btn.dataset.sort;
            var target = btn.dataset.target;
            btn.closest('.ts-sort-bar').querySelectorAll('.btn-sort').forEach(function (b) {
                b.classList.remove('active');
            });
            btn.classList.add('active');
            if (target === 'chart-ts') {
                tsSortKey = key;
                drawTs();
            } else if (target === 'chart-tmp') {
                tmpSortKey = key;
                drawTmp();
            }
        });
    });

    // ── Responsive redraw ─────────────────────────────────────────────────
    if (typeof ResizeObserver !== 'undefined') {
        var ro = new ResizeObserver(function () { drawTs(); drawTmp(); });
        if (cTs)  ro.observe(cTs);
        if (cTmp) ro.observe(cTmp);
    }
})();
