import { isBlock, isLine, isRawBlock } from "../../block";
import { createDefaultCellState, generateCellId } from "../types/notebook";
const DEFAULT_OPTIONS = {
    maxDepth: 1,
    includeLines: true,
    includeRawBlocks: true,
};
export function createCellModels(notation, options = {}) {
    const opts = Object.assign(Object.assign({}, DEFAULT_OPTIONS), options);
    const rootCell = createCellForBlock(notation, 0, opts, null);
    return rootCell.children;
}
export 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 = 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 (isBlock(item)) {
        return createCellForBlock(item, depth, options, parent);
    }
    if (isLine(item)) {
        if (!options.includeLines) {
            return null;
        }
        return createCellForLine(item, depth, options, parent);
    }
    if (isRawBlock(item)) {
        if (!options.includeRawBlocks) {
            return null;
        }
        return createCellForRawBlock(item, depth, options, parent);
    }
    return null;
}
function createCellForLine(line, depth, options, parent) {
    const state = createDefaultCellState(line, depth);
    const source = extractLineSource(line, options.notationSource);
    return {
        blockItem: line,
        state,
        source,
        children: [],
        parent,
    };
}
function createCellForRawBlock(rawBlock, depth, options, parent) {
    const state = 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]";
}
export 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;
}
export function findCellIndex(cell) {
    if (!cell.parent) {
        return -1;
    }
    return cell.parent.children.indexOf(cell);
}
export function flattenCells(cells) {
    const result = [];
    for (const cell of cells) {
        result.push(cell);
        result.push(...flattenCells(cell.children));
    }
    return result;
}
export function getVisibleCells(cells) {
    const result = [];
    for (const cell of cells) {
        result.push(cell);
        if (cell.state.isExpanded) {
            result.push(...getVisibleCells(cell.children));
        }
    }
    return result;
}
export function updateCellState(cell, updates) {
    return Object.assign(Object.assign({}, cell), { state: Object.assign(Object.assign({}, cell.state), updates) });
}
export function regenerateCellIds(cells) {
    return cells.map((cell) => (Object.assign(Object.assign({}, cell), { state: Object.assign(Object.assign({}, cell.state), { id: generateCellId() }), children: regenerateCellIds(cell.children) })));
}
//# sourceMappingURL=cellFactory.js.map