"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Editor = void 0;
var tslib_1 = require("tslib");
var React = require("react");
var ReactDOM = require("react-dom");
var operators_1 = require("rxjs/operators");
var common_1 = require("../../common");
var libs_Handsontable_1 = require("../../common/libs.Handsontable");
var provider_1 = require("./provider");
var editors = libs_Handsontable_1.Handsontable.editors;
var CSS = common_1.constants.CSS;
var Editor = (function (_super) {
    tslib_1.__extends(Editor, _super);
    function Editor() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this._ = {
            current: undefined,
        };
        _this.onCancel = function () {
            if (_this.isDisposed) {
                return;
            }
            if (_this._.current) {
                _this._.current.isCancelled = true;
            }
            var restoreOriginalValue = true;
            _this.cancelChanges();
            _this.finishEditing(restoreOriginalValue);
            _this.close();
        };
        _this.onComplete = function () {
            if (_this.isDisposed) {
                return;
            }
            common_1.time.delay(0, function () {
                var restoreOriginalValue = false;
                _this.finishEditing(restoreOriginalValue);
                _this.close();
            });
        };
        return _this;
    }
    Editor.prototype.prepare = function (row, column, prop, td, originalValue, cellProperties) {
        _super.prototype.prepare.call(this, row, column, prop, td, originalValue, cellProperties);
    };
    Object.defineProperty(Editor.prototype, "isDisposed", {
        get: function () {
            return this.instance.isDestroyed || this.grid.isDisposed;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(Editor.prototype, "isEditing", {
        get: function () {
            return Boolean(this._.current);
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(Editor.prototype, "refs", {
        get: function () {
            return this.instance.__gridRefs;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(Editor.prototype, "grid", {
        get: function () {
            return this.refs.grid;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(Editor.prototype, "cell", {
        get: function () {
            return this.grid.cell({ row: this.row, column: this.col });
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(Editor.prototype, "context", {
        get: function () {
            return this._.current;
        },
        enumerable: false,
        configurable: true
    });
    Editor.prototype.createElements = function () {
        if (this.isDisposed) {
            return;
        }
        _super.prototype.createElements.call(this);
        this.textareaStyle.display = 'none';
    };
    Editor.prototype.focus = function () {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            return tslib_1.__generator(this, function (_a) {
                return [2];
            });
        });
    };
    Editor.prototype.beginEditing = function (initialValue) {
        var _this = this;
        if (this.isDisposed) {
            return;
        }
        _super.prototype.beginEditing.call(this, initialValue);
        if (this.isEditing) {
            return;
        }
        var grid = this.grid;
        var initial = initialValue === null ? this.cell.data.value : '';
        var context = this.createContext({ initial: initial });
        var el = this.render(context);
        if (!el) {
            this.onCancel();
            return;
        }
        var row = this.row;
        var column = this.col;
        this._.current = context;
        this.grid.events$
            .pipe(operators_1.takeUntil(context.end$), operators_1.filter(function (e) { return e.type === 'GRID/cells/change'; }), operators_1.map(function (e) { return e.payload; }), operators_1.filter(function (e) { return e.isCancelled; }), operators_1.filter(function (e) { return e.changes.some(function (_a) {
            var cell = _a.cell;
            return cell.row === row && cell.column === column;
        }); }))
            .subscribe(function (e) {
            isCancelled = true;
            _this.onCancel();
        });
        var isCancelled = false;
        this.refs.editorEvents$.next({
            type: 'GRID/EDITOR/begin',
            payload: {
                get cell() {
                    return grid.cell({ row: row, column: column });
                },
                cancel: function () { return (isCancelled = true); },
            },
        });
        if (isCancelled) {
            return this.onCancel();
        }
        ReactDOM.render(el, this.TEXTAREA_PARENT);
    };
    Editor.prototype.finishEditing = function (restoreValue, ctrlDown, callback) {
        var _a;
        if (this.isDisposed) {
            return;
        }
        _super.prototype.finishEditing.call(this, restoreValue, ctrlDown, callback);
        var current = this._.current;
        if (!current) {
            return;
        }
        var grid = this.grid;
        var row = this.row;
        var column = this.col;
        var isCancelled = current.isCancelled ? true : Boolean(restoreValue);
        var from = current.value.from;
        var to = isCancelled ? from : this.getValue();
        var size = current.size;
        ReactDOM.unmountComponentAtNode(this.TEXTAREA_PARENT);
        if (size) {
            var key = common_1.coord.cell.toRowKey(this.row);
            var change = (_a = {},
                _a[key] = tslib_1.__assign(tslib_1.__assign({}, grid.data.rows[key]), { props: { grid: { height: size.height } } }),
                _a);
            grid.changeRows(change, { source: 'UPDATE/cellEdited' }).redraw();
        }
        var value = { from: from, to: to };
        var isChanged = !common_1.R.equals(value.from, value.to);
        var payload = {
            value: value,
            size: size,
            isCancelled: isCancelled,
            isChanged: isChanged,
            get cell() {
                return grid.cell({ row: row, column: column });
            },
            cancel: function () {
                var _a;
                grid.changeCells((_a = {}, _a[payload.cell.key] = from, _a), { silent: true });
                payload.isCancelled = true;
            },
        };
        var e = { type: 'GRID/EDITOR/end', payload: payload };
        this._.current = undefined;
        this.refs.editorEvents$.next(e);
    };
    Editor.prototype.getValue = function () {
        var context = this.context;
        return context ? context.value.to : undefined;
    };
    Editor.prototype.createContext = function (args) {
        var _this = this;
        var grid = this.grid;
        var cell = this.cell;
        var cancel = function () {
            context.isCancelled = true;
            _this.onCancel();
            return context;
        };
        var complete = function () {
            _this.onComplete();
            return context;
        };
        var end$ = this.refs.editorEvents$.pipe(operators_1.filter(function (e) { return e.type === 'GRID/EDITOR/end'; }), operators_1.map(function (e) { return e; }), operators_1.take(1), operators_1.share());
        var keys$ = grid.events$.pipe(operators_1.takeUntil(end$), operators_1.filter(function (e) { return e.type === 'GRID/keydown'; }), operators_1.map(function (e) { return e.payload; }), operators_1.share());
        keys$
            .pipe(operators_1.filter(function (e) { return context.autoCancel; }), operators_1.filter(function (e) { return e.isEscape; }))
            .subscribe(cancel);
        var from = this.instance.getDataAtCell(this.row, this.col);
        var value = { from: from, to: from };
        var context = {
            initial: args.initial,
            isCancelled: false,
            autoCancel: true,
            grid: grid,
            cell: cell,
            keys$: keys$,
            end$: end$,
            value: value,
            complete: complete,
            cancel: cancel,
            size: undefined,
            set: function (args) {
                if (args.value !== undefined) {
                    value.to = args.value;
                }
                if (args.size !== undefined) {
                    var _a = args.size, width = _a.width, height = _a.height;
                    context.size = { width: width, height: height };
                }
                return context;
            },
        };
        return context;
    };
    Editor.prototype.render = function (context) {
        var _a = context.cell, row = _a.row, column = _a.column;
        var _b = context.cell.data, value = _b.value, props = _b.props;
        var cell = { value: value, props: props };
        var el = this.refs.factory.editor({ row: row, column: column, cell: cell });
        if (!el) {
            return null;
        }
        var Provider = provider_1.createProvider(context);
        var className = CSS.CLASS.GRID.EDITOR;
        return (React.createElement(Provider, null,
            React.createElement("div", { className: className }, el)));
    };
    return Editor;
}(editors.TextEditor));
exports.Editor = Editor;
