/* Tabulator v4.9.3 (c) Oliver Folkerd */

var History = function History(table) {
	this.table = table; //hold Tabulator object

	this.history = [];
	this.index = -1;
};

History.prototype.clear = function () {
	this.history = [];
	this.index = -1;
};

History.prototype.action = function (type, component, data) {

	this.history = this.history.slice(0, this.index + 1);

	this.history.push({
		type: type,
		component: component,
		data: data
	});

	this.index++;
};

History.prototype.getHistoryUndoSize = function () {
	return this.index + 1;
};

History.prototype.getHistoryRedoSize = function () {
	return this.history.length - (this.index + 1);
};

History.prototype.clearComponentHistory = function (component) {
	var index = this.history.findIndex(function (item) {
		return item.component === component;
	});

	if (index > -1) {
		this.history.splice(index, 1);
		if (index <= this.index) {
			this.index--;
		}

		this.clearComponentHistory(component);
	}
};

History.prototype.undo = function () {

	if (this.index > -1) {
		var action = this.history[this.index];

		this.undoers[action.type].call(this, action);

		this.index--;

		this.table.options.historyUndo.call(this.table, action.type, action.component.getComponent(), action.data);

		return true;
	} else {
		console.warn("History Undo Error - No more history to undo");
		return false;
	}
};

History.prototype.redo = function () {
	if (this.history.length - 1 > this.index) {

		this.index++;

		var action = this.history[this.index];

		this.redoers[action.type].call(this, action);

		this.table.options.historyRedo.call(this.table, action.type, action.component.getComponent(), action.data);

		return true;
	} else {
		console.warn("History Redo Error - No more history to redo");
		return false;
	}
};

History.prototype.undoers = {
	cellEdit: function cellEdit(action) {
		action.component.setValueProcessData(action.data.oldValue);
	},

	rowAdd: function rowAdd(action) {
		action.component.deleteActual();
	},

	rowDelete: function rowDelete(action) {
		var newRow = this.table.rowManager.addRowActual(action.data.data, action.data.pos, action.data.index);

		if (this.table.options.groupBy && this.table.modExists("groupRows")) {
			this.table.modules.groupRows.updateGroupRows(true);
		}

		this._rebindRow(action.component, newRow);
	},

	rowMove: function rowMove(action) {
		this.table.rowManager.moveRowActual(action.component, this.table.rowManager.rows[action.data.posFrom], !action.data.after);
		this.table.rowManager.redraw();
	}
};

History.prototype.redoers = {
	cellEdit: function cellEdit(action) {
		action.component.setValueProcessData(action.data.newValue);
	},

	rowAdd: function rowAdd(action) {
		var newRow = this.table.rowManager.addRowActual(action.data.data, action.data.pos, action.data.index);

		if (this.table.options.groupBy && this.table.modExists("groupRows")) {
			this.table.modules.groupRows.updateGroupRows(true);
		}

		this._rebindRow(action.component, newRow);
	},

	rowDelete: function rowDelete(action) {
		action.component.deleteActual();
	},

	rowMove: function rowMove(action) {
		this.table.rowManager.moveRowActual(action.component, this.table.rowManager.rows[action.data.posTo], action.data.after);
		this.table.rowManager.redraw();
	}
};

//rebind rows to new element after deletion
History.prototype._rebindRow = function (oldRow, newRow) {
	this.history.forEach(function (action) {
		if (action.component instanceof Row) {
			if (action.component === oldRow) {
				action.component = newRow;
			}
		} else if (action.component instanceof Cell) {
			if (action.component.row === oldRow) {
				var field = action.component.column.getField();

				if (field) {
					action.component = newRow.getCell(field);
				}
			}
		}
	});
};

Tabulator.prototype.registerModule("history", History);