/*
 * Axelor Business Solutions
 *
 * Copyright (C) 2005-2017 Axelor (<http://axelor.com>).
 *
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
(function() {

/* global Handsontable: true */

"use strict";

var ui = angular.module('axelor.ui');

ui.formInput('Spreadsheet', {

	css: "spreadsheet-item",

	link: function (scope, element, attrs, model) {

		var field = scope.field;
		var height = field.height || 580;

		var inst;

		scope.$timeout(function () {

			element.height(height).css({
				"position": "relative",
				"overflow": "hidden"
			});

			inst = new Handsontable(element[0], {
				colWidths: 60,
				rowHeaders: true,
				colHeaders: true,
				contextMenu: true,
				manualColumnResize: true,
				manualRowResize: true,
				afterChange: function (change, source) {
					if (source !== 'loadData') {
						update();
					}
				},
				afterCreateCol: update,
				afterCreateRow: update,
				afterRemoveCol: update,
				afterRemoveRow: update
			});
			model.$render();
		});

		element.resizable({
			handles: 's',
			resize: function () {
				if (inst) {
					inst.render();
				}
			}
		});

		function update() {
			if (!inst) { return; }
			var current = model.$viewValue;
			var value = compact(inst.getData());

			value = value ? JSON.stringify(value) : value;
			if (value === current) {
				return;
			}
			scope.setValue(value, true);
			scope.applyLater();
		}

		function compact(items) {
			var res = [];
			var i;

			for (i = 0; i < items.length; i++) {
				var item = items[i];
				if (Array.isArray(item)) {
					item = compact(item);
				}
				if (item === "" || item === null || item === undefined || item.length === 0) {
					continue;
				}
				res[i] = item;
			}

			var n = res.length;
			for (i = n - 1; i >= 0; i--) {
				if (res[i] !== null) {
					n = i+1;
					break;
				}
			}
			res = res.slice(0, n);
			return res.length ? res : null;
		}

		function fill(data) {
			var cols = 0;
			var rows = data.length;
			var i, row;

			for(i = 0; i < data.length; i++) {
				row = data[i] || (data[i] = []);
				cols = Math.max(row.length, cols);
			}

			cols = Math.max(50, cols);
			rows = Math.max(100, rows);

			for(i = 0; i < rows; i++) {
				row = data[i] || (data[i] = []);
				for (var j = 0; j < cols + 1; j++) {
					if (row[j] === undefined) {
						row[j] = null;
					}
				}
			}

			return data;
		}

		model.$render = function () {
			var value = null;
			try {
				value = JSON.parse(model.$viewValue) || null;
			} catch (e) {
			}
			if (inst) {
				value = fill(value || []);
				inst.loadData(value || null);
				setTimeout(function () {
					inst.render();
				}, 300);
			}
		};

		scope.$on("$destroy", function () {
			if (inst) {
				inst.destroy();
				inst = null;
			}
		});
	},
	template_editable: null,
	template_readonly: null,
	template:
		"<div></div>"
});

})();
