import { assertExists, Slot } from '@blockeditor/global/utils';
import { Text } from '@blockeditor/store';
import { createUniComponentFromWebComponent } from '../../../_common/components/uni-component/uni-component.js';
import { insertPositionToIndex } from '../../utils/insert.js';
import { checkboxColumnConfig } from '../columns/checkbox/cell-renderer.js';
import { dateColumnConfig } from '../columns/date/cell-renderer.js';
import { imageColumnConfig } from '../columns/image/cell-renderer.js';
import { linkColumnConfig } from '../columns/link/cell-renderer.js';
import { columnManager } from '../columns/manager.js';
import { multiSelectColumnConfig } from '../columns/multi-select/cell-renderer.js';
import { multiSelectPureColumnConfig } from '../columns/multi-select/define.js';
import { numberColumnConfig } from '../columns/number/cell-renderer.js';
import { progressColumnConfig } from '../columns/progress/cell-renderer.js';
import { richTextColumnConfig } from '../columns/rich-text/cell-renderer.js';
import { selectColumnConfig } from '../columns/select/cell-renderer.js';
import { titleColumnConfig } from '../columns/title/cell-renderer.js';
import { BaseDataSource } from './base.js';
import { getIcon } from './block-icons.js';
import { BlockRenderer } from './block-renderer.js';
export class DatabaseBlockDatasource extends BaseDataSource {
    get page() {
        return this._model.page;
    }
    constructor(host, config) {
        super();
        this.host = host;
        this._batch = 0;
        this.slots = {
            update: new Slot(),
        };
        this._model = host.page.workspace
            .getPage(config.pageId)
            ?.getBlockById(config.blockId);
        this._model.childrenUpdated.pipe(this.slots.update);
    }
    get rows() {
        return this._model.children.map(v => v.id);
    }
    get properties() {
        return [...this._model.columns.map(column => column.id)];
    }
    _runCapture() {
        if (this._batch) {
            return;
        }
        this._batch = requestAnimationFrame(() => {
            this.page.captureSync();
            this._batch = 0;
        });
    }
    cellChangeValue(rowId, propertyId, value) {
        this._runCapture();
        const type = this.propertyGetType(propertyId);
        if (type === 'title' && typeof value === 'string') {
            const text = this.getModelById(rowId)?.text;
            if (text) {
                text.replace(0, text.length, value);
            }
            this.slots.update.emit();
            return;
        }
        else if (type === 'rich-text' && typeof value === 'string') {
            const cell = this._model.getCell(rowId, propertyId);
            const yText = cell?.value;
            if (yText) {
                const text = new Text(yText);
                text.replace(0, text.length, value);
            }
            return;
        }
        if (this._model.columns.find(v => v.id === propertyId)) {
            this._model.updateCell(rowId, {
                columnId: propertyId,
                value,
            });
            this._model.applyColumnUpdate();
        }
    }
    cellGetValue(rowId, propertyId) {
        if (propertyId === 'type') {
            const model = this.getModelById(rowId);
            if (!model) {
                return;
            }
            return getIcon(model);
        }
        const type = this.propertyGetType(propertyId);
        if (type === 'title') {
            const model = this.getModelById(rowId);
            if (model) {
                return model.text?.yText;
            }
            return;
        }
        return this._model.getCell(rowId, propertyId)?.value;
    }
    cellGetExtra(rowId, propertyId) {
        if (this.propertyGetType(propertyId) === 'title') {
            const model = this.getModelById(rowId);
            if (model) {
                return {
                    result: this.host.renderModel(model),
                    model,
                };
            }
        }
        return super.cellGetExtra(rowId, propertyId);
    }
    getModelById(rowId) {
        return this._model.children[this._model.childMap.get(rowId) ?? -1];
    }
    cellGetRenderValue(rowId, propertyId) {
        return this.cellGetValue(rowId, propertyId);
    }
    newColumnName() {
        let i = 1;
        while (this._model.columns.find(column => column.name === `Column ${i}`)) {
            i++;
        }
        return `Column ${i}`;
    }
    propertyAdd(insertToPosition, type) {
        this.page.captureSync();
        return this._model.addColumn(insertToPosition, columnManager
            .getColumn(type ?? multiSelectPureColumnConfig.type)
            .create(this.newColumnName()));
    }
    propertyChangeData(propertyId, data) {
        this._runCapture();
        this._model.updateColumn(propertyId, () => ({ data }));
        this._model.applyColumnUpdate();
    }
    propertyChangeName(propertyId, name) {
        this.page.captureSync();
        this._model.updateColumn(propertyId, () => ({ name }));
        this._model.applyColumnUpdate();
    }
    propertyChangeType(propertyId, toType) {
        const currentType = this.propertyGetType(propertyId);
        const currentData = this.propertyGetData(propertyId);
        const rows = this.rows;
        const currentCells = rows.map(rowId => this.cellGetValue(rowId, propertyId));
        const result = columnManager
            .getColumn(currentType)
            ?.convertCell(toType, currentData, currentCells) ?? {
            column: columnManager.getColumn(toType).defaultData(),
            cells: currentCells.map(() => undefined),
        };
        this.page.captureSync();
        this._model.updateColumn(propertyId, () => ({
            type: toType,
            data: result.column,
        }));
        const cells = {};
        currentCells.forEach((value, i) => {
            if (value != null || result.cells[i] != null) {
                cells[rows[i]] = result.cells[i];
            }
        });
        this._model.updateCells(propertyId, cells);
        this._model.applyColumnUpdate();
    }
    propertyDelete(id) {
        this.page.captureSync();
        const index = this._model.findColumnIndex(id);
        if (index < 0)
            return;
        this.page.transact(() => {
            this._model.columns.splice(index, 1);
        });
        this._model.applyColumnUpdate();
    }
    propertyGetData(propertyId) {
        return this._model.columns.find(v => v.id === propertyId)?.data ?? {};
    }
    propertyGetReadonly(propertyId) {
        if (propertyId === 'type')
            return true;
        return false;
    }
    propertyGetName(propertyId) {
        if (propertyId === 'type') {
            return 'Block Type';
        }
        return this._model.columns.find(v => v.id === propertyId)?.name ?? '';
    }
    propertyGetType(propertyId) {
        if (propertyId === 'type') {
            return 'image';
        }
        return this._model.columns.find(v => v.id === propertyId)?.type ?? '';
    }
    propertyDuplicate(columnId) {
        this.page.captureSync();
        const currentSchema = this._model.getColumn(columnId);
        assertExists(currentSchema);
        const { id: copyId, ...nonIdProps } = currentSchema;
        const schema = { ...nonIdProps };
        const id = this._model.addColumn({
            before: false,
            id: columnId,
        }, schema);
        this._model.copyCellsByColumn(copyId, id);
        this._model.applyColumnUpdate();
        return id;
    }
    rowAdd(insertPosition) {
        this.page.captureSync();
        const index = typeof insertPosition === 'number'
            ? insertPosition
            : insertPositionToIndex(insertPosition, this._model.children);
        return this.page.addBlock('affine:paragraph', {}, this._model.id, index);
    }
    rowDelete(ids) {
        this.page.captureSync();
        this.page.updateBlock(this._model, {
            children: this._model.children.filter(v => !ids.includes(v.id)),
        });
    }
    captureSync() {
        this.page.captureSync();
    }
    propertyGetDefaultWidth(propertyId) {
        if (this.propertyGetType(propertyId) === 'title') {
            return 260;
        }
        return super.propertyGetDefaultWidth(propertyId);
    }
    onCellUpdate(rowId, propertyId, callback) {
        if (this.propertyGetType(propertyId) === 'title') {
            this.getModelById(rowId)?.text?.yText.observe(callback);
            return {
                dispose: () => {
                    this.getModelById(rowId)?.text?.yText.unobserve(callback);
                },
            };
        }
        return this._model.propsUpdated.on(callback);
    }
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    get allPropertyConfig() {
        return [
            dateColumnConfig,
            numberColumnConfig,
            progressColumnConfig,
            selectColumnConfig,
            multiSelectColumnConfig,
            richTextColumnConfig,
            linkColumnConfig,
            checkboxColumnConfig,
        ];
    }
    get detailSlots() {
        return {
            ...super.detailSlots,
            header: createUniComponentFromWebComponent(BlockRenderer),
        };
    }
    rowMove(rowId, position) {
        const model = this.page.getBlockById(rowId);
        if (model) {
            const index = insertPositionToIndex(position, this._model.children);
            const target = this._model.children[index];
            this.page.moveBlocks([model], this._model, target);
        }
    }
}
export const hiddenColumn = [titleColumnConfig, imageColumnConfig];
//# sourceMappingURL=database-block-datasource.js.map