import { coord, R, defaultValue, util, Schema } from '../../common';
export class Cell {
    constructor(args) {
        this._ = {
            table: undefined,
            td: undefined,
        };
        this._.table = args.table;
        this.ns = args.ns;
        this.row = args.row;
        this.column = args.column;
    }
    static create(args) {
        return new Cell(args);
    }
    static createFromKey(args) {
        const { table, ns, cellKey } = args;
        const { row, column } = coord.cell.fromKey(cellKey);
        return new Cell({ table, ns, row, column });
    }
    static toKey(args) {
        return coord.cell.toKey(args.column, args.row);
    }
    static fromKey(cellKey) {
        return coord.cell.fromKey(cellKey);
    }
    static toPosition(ref) {
        return typeof ref === 'string' ? Cell.fromKey(ref) : ref;
    }
    static toRangePositions(args) {
        const range = coord.range.fromKey(args.range);
        const start = range.left;
        const end = range.right;
        if (range.type === 'COLUMN') {
            start.row = 0;
            end.row = args.totalRows - 1;
        }
        if (range.type === 'ROW') {
            start.column = 0;
            end.column = args.totalColumns - 1;
        }
        return { start, end };
    }
    static changeEvent(args) {
        const { cell, from, to } = args;
        const value = { from, to };
        let isChanged;
        const payload = {
            cell,
            value,
            get isChanged() {
                return isChanged === undefined ? (isChanged = !R.equals(value.from, value.to)) : isChanged;
            },
            isCancelled: false,
            isModified: false,
            cancel() {
                payload.isCancelled = true;
            },
            modify(change) {
                value.to = change;
                payload.isModified = true;
            },
        };
        return payload;
    }
    get isDisposed() {
        return this._.table.isDestroyed;
    }
    get key() {
        const row = this.row;
        const column = this.column;
        return Cell.toKey({ column, row });
    }
    get td() {
        this._.td = this._.td || this._.table.getCell(this.row, this.column);
        return this._.td;
    }
    get size() {
        const width = this.width;
        const height = this.height;
        return { width, height };
    }
    get width() {
        return this.td.offsetWidth;
    }
    get height() {
        return this.td.offsetHeight;
    }
    get data() {
        const data = this._.table.getDataAtCell(this.row, this.column) || {};
        if (typeof data === 'object') {
            const value = data.value;
            const props = data.props || {};
            const error = data.error;
            return { value, props, error };
        }
        else {
            return {};
        }
    }
    get siblings() {
        const table = this._.table;
        const cell = this;
        const { ns, row, column } = cell;
        return {
            get left() {
                const column = cell.column - 1;
                return column < 0 ? undefined : Cell.create({ table, ns, row, column });
            },
            get right() {
                const column = cell.column + 1;
                return column > table.countCols() - 1 ? undefined : Cell.create({ table, ns, row, column });
            },
            get top() {
                const row = cell.row - 1;
                return row < 0 ? undefined : Cell.create({ table, ns, row, column });
            },
            get bottom() {
                const row = cell.row + 1;
                return row < 0 ? undefined : Cell.create({ table, ns, row, column });
            },
        };
    }
    get rowspan() {
        return defaultValue(Cell.props(this.data.props).merge.rowspan, 1);
    }
    get colspan() {
        return defaultValue(Cell.props(this.data.props).merge.colspan, 1);
    }
    toString() {
        Schema.uri.create.cell(this.ns, this.key);
    }
}
Cell.isEmpty = util.cell.value.isEmptyCell;
Cell.isEmptyProps = util.cell.value.isEmptyCellProps;
Cell.isEmptyValue = util.cell.value.isEmptyCellValue;
Cell.diff = util.cell.value.cellDiff;
Cell.props = util.toGridCellProps;
