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

var Persistence = function Persistence(table) {
	this.table = table; //hold Tabulator object
	this.mode = "";
	this.id = "";
	this.persistProps = ["field", "width", "visible"];
};

// Test for whether localStorage is available for use.
Persistence.prototype.localStorageTest = function () {
	var testKey = "_tabulator_test";

	try {
		window.localStorage.setItem(testKey, testKey);
		window.localStorage.removeItem(testKey);
		return true;
	} catch (e) {
		return false;
	}
};

//setup parameters
Persistence.prototype.initialize = function (mode, id) {
	//determine persistent layout storage type

	this.mode = mode !== true ? mode : this.localStorageTest() ? "local" : "cookie";

	//set storage tag
	this.id = "tabulator-" + (id || this.table.element.getAttribute("id") || "");
};

//load saved definitions
Persistence.prototype.load = function (type, current) {

	var data = this.retreiveData(type);

	if (current) {
		data = data ? this.mergeDefinition(current, data) : current;
	}

	return data;
};

//retreive data from memory
Persistence.prototype.retreiveData = function (type) {
	var data = "",
	    id = this.id + (type === "columns" ? "" : "-" + type);

	switch (this.mode) {
		case "local":
			data = localStorage.getItem(id);
			break;

		case "cookie":

			//find cookie
			var cookie = document.cookie,
			    cookiePos = cookie.indexOf(id + "="),
			    end = void 0;

			//if cookie exists, decode and load column data into tabulator
			if (cookiePos > -1) {
				cookie = cookie.substr(cookiePos);

				end = cookie.indexOf(";");

				if (end > -1) {
					cookie = cookie.substr(0, end);
				}

				data = cookie.replace(id + "=", "");
			}
			break;

		default:
			console.warn("Persistence Load Error - invalid mode selected", this.mode);
	}

	return data ? JSON.parse(data) : false;
};

//merge old and new column definitions
Persistence.prototype.mergeDefinition = function (oldCols, newCols) {
	var self = this,
	    output = [];

	// oldCols = oldCols || [];
	newCols = newCols || [];

	newCols.forEach(function (column, to) {

		var from = self._findColumn(oldCols, column);

		if (from) {

			from.width = column.width;
			from.visible = column.visible;

			if (from.columns) {
				from.columns = self.mergeDefinition(from.columns, column.columns);
			}

			output.push(from);
		}
	});
	oldCols.forEach(function (column, i) {
		var from = self._findColumn(newCols, column);
		if (!from) {
			if (output.length > i) {
				output.splice(i, 0, column);
			} else {
				output.push(column);
			}
		}
	});

	return output;
};

//find matching columns
Persistence.prototype._findColumn = function (columns, subject) {
	var type = subject.columns ? "group" : subject.field ? "field" : "object";

	return columns.find(function (col) {
		switch (type) {
			case "group":
				return col.title === subject.title && col.columns.length === subject.columns.length;
				break;

			case "field":
				return col.field === subject.field;
				break;

			case "object":
				return col === subject;
				break;
		}
	});
};

//save data
Persistence.prototype.save = function (type) {
	var data = {};

	switch (type) {
		case "columns":
			data = this.parseColumns(this.table.columnManager.getColumns());
			break;

		case "filter":
			data = this.table.modules.filter.getFilters();
			break;

		case "sort":
			data = this.validateSorters(this.table.modules.sort.getSort());
			break;
	}

	var id = this.id + (type === "columns" ? "" : "-" + type);

	this.saveData(id, data);
};

//ensure sorters contain no function data
Persistence.prototype.validateSorters = function (data) {
	data.forEach(function (item) {
		item.column = item.field;
		delete item.field;
	});

	return data;
};

//save data to chosed medium
Persistence.prototype.saveData = function (id, data) {

	data = JSON.stringify(data);

	switch (this.mode) {
		case "local":
			localStorage.setItem(id, data);
			break;

		case "cookie":
			var expireDate = new Date();
			expireDate.setDate(expireDate.getDate() + 10000);

			//save cookie
			document.cookie = id + "=" + data + "; expires=" + expireDate.toUTCString();
			break;

		default:
			console.warn("Persistence Save Error - invalid mode selected", this.mode);
	}
};

//build permission list
Persistence.prototype.parseColumns = function (columns) {
	var self = this,
	    definitions = [];

	columns.forEach(function (column) {
		var def = {};

		if (column.isGroup) {
			def.title = column.getDefinition().title;
			def.columns = self.parseColumns(column.getColumns());
		} else {
			def.title = column.getDefinition().title;
			def.field = column.getField();
			def.width = column.getWidth();
			def.visible = column.visible;
		}

		definitions.push(def);
	});

	return definitions;
};

Tabulator.prototype.registerModule("persistence", Persistence);