import { header, raw } from './style.js';

const toString = (data) => {
    let t = '';
    const headerNames = [];
    const headerTitles = {};
    data.headers.forEach(h => {
        const n = h.name ?? String(h);
        headerNames.push(n);
        headerTitles[n] = h.title ?? n;
    });
    const columnWidths = {};

    if (data.type === 'columns') {
        columnWidths[0] = 0;
        data.data.forEach((col, i) => {
            columnWidths[i+1] = 0;
            for (const row of Object.keys(col)) {
                if (!headerNames.includes(row)) {
                    headerNames.push(row);
                    headerTitles[row] = row;
                }
                columnWidths[i+1] = Math.max(columnWidths[i+1], (col[row] ?? '').length);
                columnWidths[0] = Math.max(columnWidths[0], headerTitles[row].length);
            }
        });
        for (let i=0; i<headerNames.length; i++) {
            if (data.showHeaders) {
                t += header(headerTitles[headerNames[i]].padEnd(columnWidths[0]));
            }
            for (let j=0; j<data.data.length; j++) {
                const str = String(data.data[j][headerNames[i]] ?? '');
                t += ('  ' + str
                    .padEnd(
                        j === data.data.length - 1
                            ? 0
                            : (columnWidths[j+1] + (str.length - raw(str).length))
                    )
                );
            }
            t += '\n';
        }
        t = t.slice(0, -1);
    } else {
        for (const row of data.data) {
            for (const col of Object.keys(row)) {
                if (!headerNames.includes(col)) {
                    headerNames.push(col);
                    headerTitles[col] = col;
                }
                if (!columnWidths[col]) {
                    columnWidths[col] = Math.max(headerTitles[col].length, raw(String(row[col] ?? '')).length);
                } else {
                    columnWidths[col] = Math.max(columnWidths[col], raw(String(row[col] ?? '')).length);
                }
            }
        }
        if (data.showHeaders) {
            t += header(headerNames.map(n => headerTitles[n].padEnd(columnWidths[n])).join('  ')) + '\n';
        }
        t += data.data.map(
            row => headerNames.map(
                col => String(row[col] ?? '').padEnd(
                    columnWidths[col] + (String(row[col] ?? '').length - raw(String(row[col] ?? '')).length)
                )
            ).join('  ')
        ).join('\n');
    }
    return t;
};

export const table = (data = {}) => {
    if (Array.isArray(data)) {
        data = { data };
    }
    data.data ??= [];
    data.headers ??= [];
    data.type ??= 'rows';
    data.showHeaders ??= true;

    return Object.assign(Object.create({
        toString: () => toString(data)
    }), data);
};
