"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createCellModels = createCellModels;
exports.createCellModelWithRoot = createCellModelWithRoot;
exports.findCellById = findCellById;
exports.findCellIndex = findCellIndex;
exports.flattenCells = flattenCells;
exports.getVisibleCells = getVisibleCells;
exports.updateCellState = updateCellState;
exports.regenerateCellIds = regenerateCellIds;
const block_1 = require("../../block");
const notebook_1 = require("../types/notebook");
const DEFAULT_OPTIONS = {
    maxDepth: 1,
    includeLines: true,
    includeRawBlocks: true,
};
function createCellModels(notation, options = {}) {
    const opts = Object.assign(Object.assign({}, DEFAULT_OPTIONS), options);
    const rootCell = createCellForBlock(notation, 0, opts, null);
    return rootCell.children;
}
function createCellModelWithRoot(notation, options = {}) {
    const opts = Object.assign(Object.assign({}, DEFAULT_OPTIONS), options);
    return createCellForBlock(notation, 0, opts, null);
}
function createCellForBlock(block, depth, options, parent) {
    const state = (0, notebook_1.createDefaultCellState)(block, depth);
    const source = extractBlockSource(block, options.notationSource);
    const cell = {
        blockItem: block,
        state,
        source,
        children: [],
        parent,
    };
    if (depth < options.maxDepth) {
        for (const child of block.blockItems) {
            const childCell = createCellForBlockItem(child, depth + 1, options, cell);
            if (childCell) {
                cell.children.push(childCell);
            }
        }
    }
    return cell;
}
function createCellForBlockItem(item, depth, options, parent) {
    if ((0, block_1.isBlock)(item)) {
        return createCellForBlock(item, depth, options, parent);
    }
    if ((0, block_1.isLine)(item)) {
        if (!options.includeLines) {
            return null;
        }
        return createCellForLine(item, depth, options, parent);
    }
    if ((0, block_1.isRawBlock)(item)) {
        if (!options.includeRawBlocks) {
            return null;
        }
        return createCellForRawBlock(item, depth, options, parent);
    }
    return null;
}
function createCellForLine(line, depth, options, parent) {
    const state = (0, notebook_1.createDefaultCellState)(line, depth);
    const source = extractLineSource(line, options.notationSource);
    return {
        blockItem: line,
        state,
        source,
        children: [],
        parent,
    };
}
function createCellForRawBlock(rawBlock, depth, options, parent) {
    const state = (0, notebook_1.createDefaultCellState)(rawBlock, depth);
    return {
        blockItem: rawBlock,
        state,
        source: rawBlock.content,
        children: [],
        parent,
    };
}
function extractBlockSource(block, notationSource) {
    if (block.name) {
        return `\\${block.blockType}("${block.name}") { ... }`;
    }
    return `\\${block.blockType} { ... }`;
}
function extractLineSource(line, notationSource) {
    return "[Line content]";
}
function findCellById(cells, cellId) {
    for (const cell of cells) {
        if (cell.state.id === cellId) {
            return cell;
        }
        const found = findCellById(cell.children, cellId);
        if (found) {
            return found;
        }
    }
    return null;
}
function findCellIndex(cell) {
    if (!cell.parent) {
        return -1;
    }
    return cell.parent.children.indexOf(cell);
}
function flattenCells(cells) {
    const result = [];
    for (const cell of cells) {
        result.push(cell);
        result.push(...flattenCells(cell.children));
    }
    return result;
}
function getVisibleCells(cells) {
    const result = [];
    for (const cell of cells) {
        result.push(cell);
        if (cell.state.isExpanded) {
            result.push(...getVisibleCells(cell.children));
        }
    }
    return result;
}
function updateCellState(cell, updates) {
    return Object.assign(Object.assign({}, cell), { state: Object.assign(Object.assign({}, cell.state), updates) });
}
function regenerateCellIds(cells) {
    return cells.map((cell) => (Object.assign(Object.assign({}, cell), { state: Object.assign(Object.assign({}, cell.state), { id: (0, notebook_1.generateCellId)() }), children: regenerateCellIds(cell.children) })));
}
//# sourceMappingURL=cellFactory.js.map