"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.init = void 0;
var tslib_1 = require("tslib");
var operators_1 = require("rxjs/operators");
var common_1 = require("../common");
var CLIPBOARD_COMMANDS = ['CUT', 'COPY', 'PASTE'];
function init(args) {
    var grid = args.grid, command$ = args.command$, fire = args.fire;
    var clipboard$ = command$.pipe(operators_1.filter(function (e) { return CLIPBOARD_COMMANDS.includes(e.command); }), operators_1.filter(function (e) { return !e.isCancelled; }), operators_1.map(function (e) { return e.command; }));
    clipboard$.pipe(operators_1.filter(function (e) { return e === 'CUT'; })).subscribe(function (e) { return read({ grid: grid, fire: fire, action: 'CUT' }); });
    clipboard$
        .pipe(operators_1.filter(function (e) { return e === 'COPY'; }))
        .subscribe(function (e) { return read({ grid: grid, fire: fire, action: 'COPY' }); });
    clipboard$.pipe(operators_1.filter(function (e) { return e === 'PASTE'; })).subscribe(function (e) { return write({ grid: grid, fire: fire }); });
}
exports.init = init;
function read(args) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var grid, action, wait, payload;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    grid = args.grid, action = args.action;
                    wait = [];
                    args.fire({
                        type: 'GRID/clipboard/before/read',
                        payload: {
                            action: action,
                            wait: function (promise) { return wait.push(promise); },
                        },
                    });
                    if (!(wait.length > 0)) return [3, 2];
                    return [4, Promise.all(wait)];
                case 1:
                    _a.sent();
                    _a.label = 2;
                case 2:
                    payload = common_1.toClipboard({ grid: grid, action: action });
                    return [4, navigator.clipboard.writeText(payload.text)];
                case 3:
                    _a.sent();
                    grid.clipboard = tslib_1.__assign(tslib_1.__assign({}, payload), { pasted: 0 });
                    args.fire({ type: 'GRID/clipboard', payload: payload });
                    return [2];
            }
        });
    });
}
function write(args) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var grid, selection, targetCell, redraw, text, pending, before, isPendingCurrent, empty, cellsFromString, items, changedCells, shiftedAxisData, columns, rows, square, cells;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    grid = args.grid;
                    selection = grid.selection;
                    targetCell = selection.cell;
                    if (!targetCell) {
                        return [2];
                    }
                    redraw = false;
                    return [4, navigator.clipboard.readText()];
                case 1:
                    text = _a.sent();
                    pending = grid.clipboard;
                    before = {
                        text: text,
                        pending: pending,
                        isModified: false,
                        modify: function (change) {
                            before.isModified = true;
                            pending = tslib_1.__assign(tslib_1.__assign({}, (change || {})), { pasted: 0 });
                        },
                    };
                    args.fire({ type: 'GRID/clipboard/before/paste', payload: before });
                    isPendingCurrent = pending ? pending.text === text : false;
                    if (!isPendingCurrent) {
                        grid.clipboard = undefined;
                        pending = undefined;
                    }
                    if (pending && pending.action === 'CUT') {
                        empty = Object.keys(pending.cells).reduce(function (acc, key) {
                            acc[key] = { value: undefined };
                            return acc;
                        }, {});
                        grid.changeCells(empty, { source: 'CLIPBOARD/cut' });
                    }
                    cellsFromString = function () {
                        return common_1.coord.table
                            .fromString({ key: targetCell, text: text })
                            .map(function (_a) {
                            var key = _a.key, value = _a.value;
                            return ({ key: key, value: { value: value } });
                        });
                    };
                    items = pending && pending.selection.cell
                        ? shiftCells({
                            sourceCell: pending.selection.cell,
                            targetCell: targetCell,
                            data: pending.cells,
                        })
                        : cellsFromString();
                    if (items.length === 0) {
                        return [2];
                    }
                    changedCells = items.reduce(function (acc, next) {
                        acc[next.key] = next.value;
                        return acc;
                    }, {});
                    grid.changeCells(changedCells, { source: 'CLIPBOARD/paste' });
                    shiftedAxisData = function (axis, data) {
                        if (!pending || Object.keys(data).length === 0) {
                            return {};
                        }
                        var source = firstAxisRange(axis, pending.selection);
                        var target = firstAxisRange(axis, selection);
                        if (!source || !target) {
                            return {};
                        }
                        return shiftAxisData({ axis: axis, source: source, target: target, data: data });
                    };
                    columns = pending ? shiftedAxisData('COLUMN', pending.columns) : {};
                    rows = pending ? shiftedAxisData('ROW', pending.rows) : {};
                    if (Object.keys(columns).length > 0) {
                        grid.changeColumns(columns, { source: 'CLIPBOARD/paste' });
                        redraw = true;
                    }
                    if (Object.keys(rows).length > 0) {
                        grid.changeRows(rows, { source: 'CLIPBOARD/paste' });
                        redraw = true;
                    }
                    square = common_1.coord.range.square(items.map(function (item) { return item.key; }));
                    grid.select({ cell: square.left.key, ranges: [square.key] });
                    if (grid.clipboard) {
                        grid.clipboard = tslib_1.__assign(tslib_1.__assign({}, grid.clipboard), { pasted: grid.clipboard.pasted + 1 });
                    }
                    cells = items.reduce(function (acc, next) {
                        acc[next.key] = next.value;
                        return acc;
                    }, {});
                    args.fire({
                        type: 'GRID/clipboard',
                        payload: { action: 'PASTE', selection: selection, text: text, cells: cells, columns: columns, rows: rows },
                    });
                    if (redraw) {
                        grid.redraw();
                    }
                    return [2];
            }
        });
    });
}
function shiftCells(args) {
    var pos = {
        start: common_1.coord.cell.fromKey(args.sourceCell),
        end: common_1.coord.cell.fromKey(args.targetCell),
    };
    var diff = {
        row: pos.end.row - pos.start.row,
        column: pos.end.column - pos.start.column,
    };
    var data = tslib_1.__assign({}, args.data);
    return Object.keys(data).map(function (cell) {
        var pos = common_1.coord.cell.fromKey(cell);
        var key = common_1.coord.cell.toKey(pos.column + diff.column, pos.row + diff.row);
        return { key: key, value: data[cell] };
    });
}
function shiftAxisData(args) {
    var axis = args.axis;
    var pos = {
        start: args.source.left,
        end: args.target.left,
    };
    var diff = common_1.coord.cell.toAxisIndex(axis, pos.end) - common_1.coord.cell.toAxisIndex(axis, pos.start);
    var data = tslib_1.__assign({}, args.data);
    return Object.keys(data).reduce(function (acc, next) {
        var index = common_1.coord.cell.toAxisIndex(axis, next) + diff;
        var key = common_1.coord.cell.toAxisKey(axis, index);
        if (key) {
            acc[key] = data[next];
        }
        return acc;
    }, {});
}
function firstAxisRange(axis, selection) {
    var key = selection.ranges.find(function (key) { return common_1.coord.cell.isAxisRangeKey(key, axis); });
    return key ? common_1.coord.range.fromKey(key) : undefined;
}
