"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.serializeCells = serializeCells;
exports.serializeCell = serializeCell;
exports.serializeBlockItem = serializeBlockItem;
exports.updateCellSource = updateCellSource;
exports.validateCellSource = validateCellSource;
exports.findCellSourceRange = findCellSourceRange;
const block_1 = require("../../block");
const DEFAULT_OPTIONS = {
    indent: "  ",
    lineSeparator: "\n",
    preserveUnmodified: true,
};
function serializeCells(cells, options = {}) {
    const opts = Object.assign(Object.assign({}, DEFAULT_OPTIONS), options);
    const parts = [];
    for (const cell of cells) {
        const serialized = serializeCell(cell, 0, opts);
        if (serialized) {
            parts.push(serialized);
        }
    }
    return parts.join(opts.lineSeparator + opts.lineSeparator);
}
function serializeCell(cell, depth, options) {
    const indent = options.indent.repeat(depth);
    if (options.preserveUnmodified && cell.source && !cell.state.hasError) {
        if (depth === 0) {
            return cell.source;
        }
        return cell.source
            .split("\n")
            .map((line) => indent + line)
            .join(options.lineSeparator);
    }
    return serializeBlockItem(cell.blockItem, depth, options);
}
function serializeBlockItem(item, depth, options) {
    if ((0, block_1.isRawBlock)(item)) {
        return serializeRawBlock(item, depth, options);
    }
    if ((0, block_1.isLine)(item)) {
        return serializeLine(item, depth, options);
    }
    if ((0, block_1.isBlock)(item)) {
        return serializeBlock(item, depth, options);
    }
    return "";
}
function serializeRawBlock(rawBlock, depth, options) {
    const indent = options.indent.repeat(depth);
    const content = rawBlock.content;
    if (rawBlock.contentType === "md") {
        return `${indent}---${options.lineSeparator}${content}${options.lineSeparator}${indent}---`;
    }
    if (rawBlock.contentType === "metadata") {
        return `${indent}@@${content}`;
    }
    return content
        .split("\n")
        .map((line) => indent + line)
        .join(options.lineSeparator);
}
function serializeLine(line, depth, options) {
    const indent = options.indent.repeat(depth);
    return `${indent}; [Line serialization not fully implemented]`;
}
function serializeBlock(block, depth, options) {
    const indent = options.indent.repeat(depth);
    const childIndent = options.indent.repeat(depth + 1);
    const parts = [];
    const header = serializeBlockHeader(block);
    parts.push(`${indent}${header} {`);
    for (const child of block.blockItems) {
        const childSource = serializeBlockItem(child, depth + 1, options);
        if (childSource) {
            parts.push(childSource);
        }
    }
    parts.push(`${indent}}`);
    return parts.join(options.lineSeparator);
}
function serializeBlockHeader(block) {
    var _a;
    const type = block.blockType;
    switch (type) {
        case "section":
            return `\\section("${block.name || ""}")`;
        case "repeat": {
            const repeatCount = (_a = block.repeatCount) !== null && _a !== void 0 ? _a : 1;
            return `\\repeat(${repeatCount})`;
        }
        case "cycle":
            if (block.localCycle) {
                return `\\cycle("${block.localCycle.toString()}")`;
            }
            return "\\cycle()";
        case "beatduration":
            if (block.localAtomsPerBeat !== null) {
                return `\\beatDuration(${block.localAtomsPerBeat})`;
            }
            return "\\beatDuration(1)";
        case "breaks":
            if (block.localBreaks) {
                return `\\breaks(${block.localBreaks.join(", ")})`;
            }
            return "\\breaks()";
        case "role": {
            const roleName = Array.from(block.localRoles.keys())[0] || "";
            return `\\role("${roleName}")`;
        }
        case "group":
            if (block.name) {
                return `\\group("${block.name}")`;
            }
            return "\\group()";
        case "notation":
            return "";
        default:
            return `\\${type}()`;
    }
}
function updateCellSource(cell, newSource) {
    return Object.assign(Object.assign({}, cell), { source: newSource });
}
function validateCellSource(source) {
    let braceCount = 0;
    for (const char of source) {
        if (char === "{")
            braceCount++;
        if (char === "}")
            braceCount--;
        if (braceCount < 0) {
            return {
                isValid: false,
                error: "Unmatched closing brace",
            };
        }
    }
    if (braceCount !== 0) {
        return {
            isValid: false,
            error: "Unmatched opening brace",
        };
    }
    return { isValid: true };
}
function findCellSourceRange(cell, fullSource) {
    if ((0, block_1.isRawBlock)(cell.blockItem)) {
        const rawBlock = cell.blockItem;
        const start = fullSource.indexOf(rawBlock.content);
        if (start >= 0) {
            return {
                start,
                end: start + rawBlock.content.length,
            };
        }
    }
    return null;
}
//# sourceMappingURL=sourceSerializer.js.map