/*!
 SerializeJSON jQuery plugin.
 https://github.com/marioizquierdo/jquery.serializeJSON
 version 2.6.2 (May, 2015)

 Copyright (c) 2012, 2015 Mario Izquierdo
 Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 */
!function(e){if("function"==typeof define&&define.amd)define(["jquery"],e);else if("object"==typeof exports){var n=require("jquery");module.exports=e(n)}else e(window.jQuery||window.Zepto||window.$)}(function(e){"use strict";e.fn.serializeJSON=function(n){var r,t,s,i,a,u,o;return u=e.serializeJSON,o=u.setupOpts(n),t=this.serializeArray(),u.readCheckboxUncheckedValues(t,this,o),r={},e.each(t,function(e,n){s=u.splitInputNameIntoKeysArray(n.name,o),i=s.pop(),"skip"!==i&&(a=u.parseValue(n.value,i,o),o.parseWithFunction&&"_"===i&&(a=o.parseWithFunction(a,n.name)),u.deepSet(r,s,a,o))}),r},e.serializeJSON={defaultOptions:{checkboxUncheckedValue:void 0,parseNumbers:!1,parseBooleans:!1,parseNulls:!1,parseAll:!1,parseWithFunction:null,customTypes:{},defaultTypes:{string:function(e){return String(e)},number:function(e){return Number(e)},"boolean":function(e){var n=["false","null","undefined","","0"];return-1===n.indexOf(e)},"null":function(e){var n=["false","null","undefined","","0"];return-1===n.indexOf(e)?e:null},array:function(e){return JSON.parse(e)},object:function(e){return JSON.parse(e)},auto:function(n){return e.serializeJSON.parseValue(n,null,{parseNumbers:!0,parseBooleans:!0,parseNulls:!0})}},useIntKeysAsArrayIndex:!1},setupOpts:function(n){var r,t,s,i,a,u;u=e.serializeJSON,null==n&&(n={}),s=u.defaultOptions||{},t=["checkboxUncheckedValue","parseNumbers","parseBooleans","parseNulls","parseAll","parseWithFunction","customTypes","defaultTypes","useIntKeysAsArrayIndex"];for(r in n)if(-1===t.indexOf(r))throw new Error("serializeJSON ERROR: invalid option '"+r+"'. Please use one of "+t.join(", "));return i=function(e){return n[e]!==!1&&""!==n[e]&&(n[e]||s[e])},a=i("parseAll"),{checkboxUncheckedValue:i("checkboxUncheckedValue"),parseNumbers:a||i("parseNumbers"),parseBooleans:a||i("parseBooleans"),parseNulls:a||i("parseNulls"),parseWithFunction:i("parseWithFunction"),typeFunctions:e.extend({},i("defaultTypes"),i("customTypes")),useIntKeysAsArrayIndex:i("useIntKeysAsArrayIndex")}},parseValue:function(n,r,t){var s,i;return i=e.serializeJSON,s=t.typeFunctions&&t.typeFunctions[r],s?s(n):t.parseNumbers&&i.isNumeric(n)?Number(n):!t.parseBooleans||"true"!==n&&"false"!==n?t.parseNulls&&"null"==n?null:n:"true"===n},isObject:function(e){return e===Object(e)},isUndefined:function(e){return void 0===e},isValidArrayIndex:function(e){return/^[0-9]+$/.test(String(e))},isNumeric:function(e){return e-parseFloat(e)>=0},optionKeys:function(e){if(Object.keys)return Object.keys(e);var n,r=[];for(n in e)r.push(n);return r},splitInputNameIntoKeysArray:function(n,r){var t,s,i,a,u;return u=e.serializeJSON,a=u.extractTypeFromInputName(n,r),s=a[0],i=a[1],t=s.split("["),t=e.map(t,function(e){return e.replace(/\]/g,"")}),""===t[0]&&t.shift(),t.push(i),t},extractTypeFromInputName:function(n,r){var t,s,i;if(t=n.match(/(.*):([^:]+)$/)){if(i=e.serializeJSON,s=i.optionKeys(r?r.typeFunctions:i.defaultOptions.defaultTypes),s.push("skip"),-1!==s.indexOf(t[2]))return[t[1],t[2]];throw new Error("serializeJSON ERROR: Invalid type "+t[2]+" found in input name '"+n+"', please use one of "+s.join(", "))}return[n,"_"]},deepSet:function(n,r,t,s){var i,a,u,o,l,c;if(null==s&&(s={}),c=e.serializeJSON,c.isUndefined(n))throw new Error("ArgumentError: param 'o' expected to be an object or array, found undefined");if(!r||0===r.length)throw new Error("ArgumentError: param 'keys' expected to be an array with least one element");i=r[0],1===r.length?""===i?n.push(t):n[i]=t:(a=r[1],""===i&&(o=n.length-1,l=n[o],i=c.isObject(l)&&(c.isUndefined(l[a])||r.length>2)?o:o+1),""===a?(c.isUndefined(n[i])||!e.isArray(n[i]))&&(n[i]=[]):s.useIntKeysAsArrayIndex&&c.isValidArrayIndex(a)?(c.isUndefined(n[i])||!e.isArray(n[i]))&&(n[i]=[]):(c.isUndefined(n[i])||!c.isObject(n[i]))&&(n[i]={}),u=r.slice(1),c.deepSet(n[i],u,t,s))},readCheckboxUncheckedValues:function(n,r,t){var s,i,a,u,o;null==t&&(t={}),o=e.serializeJSON,s="input[type=checkbox][name]:not(:checked):not([disabled])",i=r.find(s).add(r.filter(s)),i.each(function(r,s){a=e(s),u=a.attr("data-unchecked-value"),u?n.push({name:s.name,value:u}):o.isUndefined(t.checkboxUncheckedValue)||n.push({name:s.name,value:t.checkboxUncheckedValue})})}}});




var g_stbDiagramAxeColorTimeoutSet = false,
	g_stbDiagramAxeColorLast = '',
	g_stbDiagramCurRange = null,
	chartCreateData = {},
	chartRerenderParams = {},
	rerenderedCharts = {},
	$previewDialog;
(function ($, app, undefined) {

	/***********************************************************/
	function stbChart() {

	}
	stbChart.prototype.isNumeric = (function(n) {
		return !isNaN(parseFloat(n)) && isFinite(n);
	});
	stbChart.prototype.fillArray = (function(count, fillData) {
		return Array.apply(null, Array(count)).map(function() {
			return fillData;
		});
	});
	stbChart.prototype.formatHeaders = (function(data) {
		var isRerender = chartRerenderParams.needRerender
		,	switchRowsColumns = (isRerender && chartRerenderParams.switchRowsColumns) || (!isRerender && $('#switchRowsColumns').is(':checked'))
		,   showLabelIntoDiagram = (isRerender && chartRerenderParams.showLabelIntoDiagram) || (!isRerender && $('#showLabelIntoDiagram').is(':checked'))
		,	useFirstRow = (isRerender && chartRerenderParams.useFirstRow) || (!isRerender && $('#useFirstRow').is(':checked'))
		,	useFirstColumn = (isRerender && chartRerenderParams.useFirstColumn) || (!isRerender && $('#useFirstColumn').is(':checked'));

		if (!switchRowsColumns) {
			// Headers
			if (!useFirstRow) {
				if (data[0] instanceof Array) {
					for (var i = 0; i < data[0].length; i++) {
						if (this.isNumeric(data[0][i])) {
							data.splice(0, 0, this.fillArray(data[0].length, ""));
							break;
						}
					}
				}
			} else {
				for (var i = 0; i < data[0].length; i++) {
					data[0][i] = typeof data[0][i] !== 'object' ? String(data[0][i]) : data[0][i];
				}
			}
			// Labels
			if (!useFirstColumn) {
				for (var i = 0; i < data.length; i++) {
					if (this.isNumeric(data[i][0])) {
						for (var i = 0; i < data.length; i++) {
							data[i].splice(0, 0, "");
						}
						break;
					}
				}
			} else {
				for (var i = 0; i < data.length; i++) {
					data[i][0] = typeof data[i][0] !== 'object' ? String(data[i][0]) : data[i][0];
				}
			}

		} else {
			// Labels
			if (useFirstRow) {
				for (var i = 0; i < data[0].length; i++) {
                    data[0][i] = typeof data[0][i] !== 'object' ? String(data[0][i]) : data[0][i];
				}
			} else {
				if (typeof data[1][0] !== 'string') {
					for (var i = 0; i < data.length; i++) {
						data[i].splice(0, 0, "");
					}
				}
			}
			// Headers
			if (!useFirstColumn) {
				if (data[0] instanceof Array) {
					for (var i = 0; i < data[0].length; i++) {
						if (!this.isNumeric(data[0][i])) {
							for (var j = 0; j < data[0].length; j++) {
								data[0][j] = "";
							}
							break;
						}
					}
				}
			} else {
				for (var i = 0; i < data[0].length; i++) {
                    data[0][i] = typeof data[0][i] !== 'object' ? String(data[0][i]) : data[0][i];
				}
			}
		}

		if (data[0].length < 2) {
			data.splice(0, 0, this.fillArray(data[0].length, ""));
		}

		return data;
	});

	stbChart.prototype.formatColumns = (function(dataColumns, chartType) {

		if (!(dataColumns[0] instanceof Array)) {
			for (var i = 0; i < dataColumns.length; i++) {
				dataColumns[i] = [dataColumns[i]];
			}
		}

		for (var i = 0; i < dataColumns.length; i++) {
			for (var j = 0; j < dataColumns[i].length; j++) {
            if ((typeof dataColumns[i][j] !== 'undefined') &&
   					!isNaN(Number(dataColumns[i][j])) &&
   					dataColumns[i][j].length) {
   					dataColumns[i][j] = typeof dataColumns[i][j] !== 'object' ? Number(dataColumns[i][j]) : dataColumns[i][j];
   				}
			}
		}
		return this.formatHeaders(dataColumns);
	});

	stbChart.prototype.formatRows = (function(dataRows, chartType) {
		var dataTemp = [];

		if (!(dataRows[0] instanceof Array)) {
			for (var i = 0; i < dataRows.length; i++) {
				dataRows[i] = [dataRows[i]];
			}
		}

		for (var i = 0; i < dataRows.length; i++) {
			for (var j = 0; j < dataRows[i].length; j++) {
				dataTemp[j] = dataTemp[j] || [];
				dataTemp[j][i] = dataTemp[j][i] || [];
				if (!isNaN(Number(dataRows[i][j])) && dataRows[i][j].length) {
					dataTemp[j][i] = typeof dataRows[i][j] !== 'object' ? Number(dataRows[i][j]) : dataRows[i][j];
				} else {
					dataTemp[j][i] = dataRows[i][j];
				}
			}
		}

		return this.formatHeaders(dataTemp);
	});

	stbChart.prototype.prepareChartData = (function(selRangData, chartType) {
		var rangeData
		,	isRerender = chartRerenderParams.needRerender;

		if ((isRerender && chartRerenderParams.switchRowsColumns) || (!isRerender && $('#switchRowsColumns').is(':checked'))) {
			rangeData = this.formatRows(selRangData, chartType);
		} else {
			rangeData = this.formatColumns(selRangData, chartType);
		}
		return rangeData;
	});

	/***********************************************************/
	function stbGoogleChart() {
		stbChart.apply(this, arguments);
	}
	stbGoogleChart.prototype = Object.create(stbChart.prototype);
	stbGoogleChart.prototype.constructor = stbGoogleChart;

	stbGoogleChart.prototype.prepareOptions = (function(options) {
		var defaults = {
			width: '100%',
			height: '100%',
			pointSize: 5,
			chartArea: {
				width: "80%",
				height: "80%",
				top: "10%",
				left: "10%",
				right: "10%",
				bottom: "10%"
			}
		};

		if(options && !options.isPreview) {
			options.chartArea.width = (100 - options.chartArea.left - options.chartArea.right) + '%';
			options.chartArea.height = (100 - options.chartArea.top - options.chartArea.bottom) + '%';
			options.chartArea.top = options.chartArea.top ? options.chartArea.top + '%' : defaults.chartArea.top;
			options.chartArea.left = options.chartArea.left ? options.chartArea.left + '%' : defaults.chartArea.left;
			options.chartArea.right = options.chartArea.right ? options.chartArea.right + '%' : defaults.chartArea.right;
			options.chartArea.bottom = options.chartArea.bottom ? options.chartArea.bottom + '%' : defaults.chartArea.bottom;
		}
		options = $.extend(defaults, options);
		return options;
	});

    stbGoogleChart.prototype.prepareChartData = (function(selRangData, chartType) {
        var rangeData
            ,   isRerender = chartRerenderParams.needRerender
            ,	switchRowsColumns = (isRerender && chartRerenderParams.switchRowsColumns) || (!isRerender && $('#switchRowsColumns').is(':checked'))
            ,	useFirstRow = (isRerender && chartRerenderParams.useFirstRow) || (!isRerender && $('#useFirstRow').is(':checked'))
            ,	useFirstColumn = (isRerender && chartRerenderParams.useFirstColumn) || (!isRerender && $('#useFirstColumn').is(':checked'))
            ,   showLabelIntoDiagram = (isRerender && chartRerenderParams.showLabelIntoDiagram) || (!isRerender && $('#showLabelIntoDiagram').is(':checked'))
            ,   tmpData = [];
						if (chartType == 'PieChart') {
							showLabelIntoDiagram = false;
						}
        if (
            !switchRowsColumns
            && (useFirstRow || useFirstColumn)
            && showLabelIntoDiagram
        ) {
            for (var i = 0; i < selRangData.length; i++) {
                for (var j = 0; j < selRangData[i].length; j++) {
                    if (typeof tmpData[i] === 'undefined') {
                        tmpData[i] = [];
                    }
                    if (useFirstRow && useFirstColumn) {
                        if (j == 0) {
                            tmpData[i].push(selRangData[i][j]);
                            continue;
                        }
                        if (i == 0) {
                            tmpData[i].push(selRangData[i][j], {'role': 'annotation'});
                        } else {
                            tmpData[i].push(selRangData[i][j], String(selRangData[i][j]));
                        }
                    } else if (useFirstRow) {
                        if (i == 0) {
                            tmpData[i].push(selRangData[i][j], {'role': 'annotation'});
                        } else {
                            tmpData[i].push(selRangData[i][j], String(selRangData[i][j]));
                        }
                    } else {
                        tmpData[i].push(selRangData[i][j]);
					}
                }
            }
            selRangData = tmpData;
        } else if (
            switchRowsColumns
            && (useFirstRow || useFirstColumn)
            && showLabelIntoDiagram
        ) {
            for (var i = 0; i < selRangData.length; i++) {
                tmpData = tmpData || [];

                tmpData.push(selRangData[i]);

                if (useFirstColumn) { // headers
                    var localTmpData = [];
                    for (var j = 0; j < selRangData[i].length; j++) {
                        if (j == 0) {
                            localTmpData[j] = {'role': 'annotation'};
                        } else {
                            localTmpData[j] = String(selRangData[i][j]);
                        }
                    }
                    tmpData.push(localTmpData);
                }
            }
            selRangData = tmpData;
        }

        if (showLabelIntoDiagram) {
            chartCreateData.dontRecalc = 1;
		}

        if (switchRowsColumns) {
            rangeData = this.formatRows(selRangData, chartType);
        } else {
            rangeData = this.formatColumns(selRangData, chartType);
        }

        return rangeData;
    });

	stbGoogleChart.prototype.drawChart = (function(preparedData, options, chartId, canvasId) {
		var chart = new google.visualization[chartId](document.getElementById(canvasId)),
			chartData = new google.visualization.arrayToDataTable(preparedData);
		options = this.prepareOptions(options);


		var rows = chartData.getNumberOfRows();
		var cols = chartData.getNumberOfColumns();

		if (chartId != 'PieChart') {
			var formatter = new google.visualization.NumberFormat({
			  pattern:'#,##%'
			});

			if ( (typeof options != 'undefined') && (options.vAxis.format == "#.##%" || options.vAxis.format == "##.##%") ) {
				for (var i = 0; i < cols; i++) {
					formatter.format(chartData, i);
				}
			}

			if ( (typeof options != 'undefined') && (options.hAxis.format == "#.##%" || options.hAxis.format == "##.##%") ) {
				for (var i = 0; i < rows; i++) {
					formatter.format(chartData, i);
				}
			}
		}

		chart.draw(chartData, options);

		if(options.legend && options.legend.position && options.legend.toggling
			&& options.legend.position != 'none' && options.legend.position != 'labeled' && options.legend.toggling == 'remove') {
			drawGoogleChartWithToggling(chart, chartData, options, chartId);
		}
	});

	/***********************************************************/
	function stbZingChart() {
		stbChart.apply(this, arguments);
	}
	stbZingChart.prototype = Object.create(stbChart.prototype);
	stbZingChart.prototype.constructor = stbZingChart;

	stbZingChart.prototype.rotateData = (function(tableValues) {
		var ind = 0
		,	indJ = 0
		,	zingPrepared = []
		;
		for(ind = 0; ind < tableValues.length; ind++) {
			if(tableValues[ind] && tableValues[ind].length) {
				for(indJ = 0; indJ < tableValues[ind].length; indJ++) {
					if(!zingPrepared[indJ]) {
						zingPrepared[indJ] = [];
					}
					zingPrepared[indJ][ind] = tableValues[ind][indJ];
				}
			}
		}
		return zingPrepared;
	});

	stbZingChart.prototype.prepareChartData = (function(tableValues, chartId, options) {
		var zingChartType = 'bar3d'
		,	tableData
		,	isRerender = chartRerenderParams.needRerender
		,	isSwitchRowsAndColumns = (isRerender && chartRerenderParams.switchRowsColumns) || (!isRerender && $('#switchRowsColumns').is(':checked'))
		,	isUseFirstRow = (isRerender && chartRerenderParams.useFirstRow) || (!isRerender && $('#useFirstRow').is(':checked'))
		,	isUseFirstColumn = (isRerender && chartRerenderParams.useFirstColumn) || (!isRerender && $('#useFirstColumn').is(':checked'))
        ,   showLabelIntoDiagram = (isRerender && chartRerenderParams.showLabelIntoDiagram) || (!isRerender && $('#showLabelIntoDiagram').is(':checked'))
		,	chartData = {
			"type": zingChartType,
			"plot": {},
		}
		;

		switch(chartId) {
			case 'BarChart3d':
				chartData['plot']['aspect'] = 'bar';
				break;
			case 'PieChart3d':
				chartData['type'] = 'pie3d';
				chartData['plot']['value-box'] = {};
				chartData['plot']['value-box']['visible'] = false;
				break;
			case 'PyramidChart3d':
				chartData['plot']['aspect'] = 'pyramid';
				chartData['plot']['stacked'] = true;
                chartData['plot']['value-box'] = {};
                chartData['plot']['value-box']['placement'] = "center";
                chartData['plot']['value-box']['visible'] = false;
				break;
			case 'DonutChart3d':
				chartData['type'] = 'ring3d';
				chartData['plot']['value-box'] = {};
				chartData['plot']['value-box']['visible'] = false;
				break;
		}

		if (showLabelIntoDiagram) {
            chartData['plot']['value-box'] = chartData['plot']['value-box'] || {};
            chartData['plot']['value-box']['text'] = "%v";
            chartData['plot']['value-box']['font-color'] = "#000";
            chartData['plot']['value-box']['visible'] = true;
            chartCreateData.dontRecalc = 1;
        }

		var fullChartData = {}
		,	preparedArr = this.prepareTableData(tableValues, isSwitchRowsAndColumns, isUseFirstRow, isUseFirstColumn);

		if(preparedArr && preparedArr.chartData) {
			chartData['series'] = preparedArr.chartData;
		}

		if(options) {
			if(options.chartArea) {
				chartData['plotarea'] = {};
				if(options.chartArea.bottom) {
					chartData['plotarea']['margin-bottom'] = options.chartArea.bottom;
				}
				if(options.chartArea.left) {
					chartData['plotarea']['margin-left'] = options.chartArea.left;
				}
				if(options.chartArea.right) {
					chartData['plotarea']['margin-right'] = options.chartArea.right;
				}
				if(options.chartArea.top) {
					chartData['plotarea']['margin-top'] = options.chartArea.top;
				}
			}
			if(options.chart_height) {
				fullChartData['height'] = options.chart_height;
			}
			if(options.chart_width) {
				fullChartData['width'] = options.chart_width;
			}
			if(options.en_custom_colors == 'on' && options.colors && options.colors.length && chartData['series'].length) {
				var indI = 0;
				for(indI = 0; indI < options.colors.length; indI++) {
					if(indI < chartData['series'].length) {
						chartData['series'][indI]['background-color'] = options.colors[indI];
					}
				}
			}
            if(options.en_custom_colors == 'on' && options.value_color && options.value_color.length && chartData['series'].length && showLabelIntoDiagram) {
                chartData['plot']['value-box'] = {
                	"text": "%v",
					"font-color": options.value_color
                };
            }

			chartData['scale-x'] = {};
			chartData['scale-x']['thousands-separator'] = '';
			if(preparedArr && preparedArr.rowNameArr && preparedArr.rowNameArr.length) {
				chartData['scale-x']['values'] = preparedArr.rowNameArr;
			}
			if(options.hAxis) {
				if(options.hAxis.format) {
					switch(options.hAxis.format) {
						// Percent
						case '##.##%':
							chartData['scale-x']['format'] = '%v%';
							break;
						// Currency
						case '$#,###.##':
							chartData['scale-x']['format'] = "$%v";
							chartData['scale-x']['decimals-separator'] = '.';
							chartData['scale-x']['thousands-separator'] = ",";
							break;
						// Number
						case '#,###.##':
							chartData['scale-x']['decimals-separator'] = '.';
							chartData['scale-x']['thousands-separator'] = ",";
							break;
						// Short Number
						case 'short':
							chartData['scale-x']['thousands-separator'] = '.';
							chartData['scale-x']['short'] = true;
							break;
						// Long Number
						//case 'long':
						//	chartData['scale-x']['thousands-separator'] = '.';
						//	chartData['scale-x']['short'] = true;
						//	chartData['scale-x']['short-unit'] = 'tho...';
						//	break;
						// Scientific
						case 'scientific':
							chartData['scale-x']['exponent'] = true;
							chartData['scale-x']['exponent-decimals'] = 0;
							break;
					}

				}
				if(options.hAxis.title) {
					chartData['scale-x']['label'] = {};
					chartData['scale-x']['label']['text'] = options.hAxis.title;
					chartData['scale-x']['label']['font-color'] = '#000';
					chartData['scale-x']['label']['font-size'] = 12;
				}
			}
			chartData['scale-y'] = {};
			chartData['scale-y']['thousands-separator'] = '';
			if(preparedArr && preparedArr.columnNameArr && preparedArr.columnNameArr.length) {
				chartData['scale-y']['values'] = preparedArr.columnNameArr;
			}
			if(options.vAxis) {
				if(options.vAxis.format) {
					switch(options.vAxis.format) {
						// Percent
						case '##.##%':
							chartData['scale-y']['format'] = '%v%';
							break;
						// Currency
						case '$#,###.##':
							chartData['scale-y']['format'] = "$%v";
							chartData['scale-y']['decimals-separator'] = '.';
							chartData['scale-y']['thousands-separator'] = ",";
							break;
						// Number
						case '#,###.##':
							chartData['scale-y']['decimals-separator'] = '.';
							chartData['scale-y']['thousands-separator'] = ",";
							break;
						// Short Number
						case 'short':
							chartData['scale-y']['thousands-separator'] = '.';
							chartData['scale-y']['short'] = true;
							break;
						// Long Number
						//case 'long':
						//	chartData['scale-y']['thousands-separator'] = '.';
						//	chartData['scale-y']['short'] = true;
						//	chartData['scale-y']['short-unit'] = 'tho...';
						//	break;
						// Scientific
						case 'scientific':
							chartData['scale-y']['exponent'] = true;
							chartData['scale-y']['exponent-decimals'] = 0;
							break;
					}
				}
				if(options.vAxis.title) {
					chartData['scale-y']['label'] = {};
					chartData['scale-y']['label']['text'] = options.vAxis.title;
					chartData['scale-y']['label']['font-color'] = '#000';
					chartData['scale-y']['label']['font-size'] = 12;
				}
			}
			if(options.legend) {
				if(options.legend.position) {
					switch(options.legend.position) {
						case 'top':
							chartData['legend'] = {
								'vertical-align': 'top',
								'align': 'center',
								'toggle-action': options.legend.toggling,
							};
							break;
						case 'bottom':
							chartData['legend'] = {
								'vertical-align': 'bottom',
								'align': 'center',
								'toggle-action': options.legend.toggling,
							};
							break;
						case 'left':
							chartData['legend'] = {
								'vertical-align': 'middle',
								'align': 'left',
								'toggle-action': options.legend.toggling,
							};
							break;
						case 'right':
							chartData['legend'] = {
								'vertical-align': 'middle',
								'align': 'right',
								'toggle-action': options.legend.toggling,
							};
							break;
						default:
							break;
					}
				}
			}
			if(options.title) {
				chartData['title'] = {};
				chartData['title']['text'] = options.title;
				chartData['title']['color'] = '#000';
			}
			if(options.aspect3d) {
				chartData['3d-aspect'] = {};
				if(options.aspect3d.xAngle) {
					chartData['3d-aspect']['x-angle'] = options.aspect3d.xAngle;
				}
				if(options.aspect3d.yAngle) {
					chartData['3d-aspect']['y-angle'] = options.aspect3d.yAngle;
				}
				if(options.aspect3d.zAngle) {
					chartData['3d-aspect']['z-angle'] = options.aspect3d.zAngle;
				}
			}
		}

		fullChartData['data'] = chartData;
		return fullChartData;
	});

	stbZingChart.prototype.prepareTableData = (function(tableValues, isSwitchRowsAndColumns, isUseFirstRow, isUseFirstColumn) {
		var tblAssArr = []
		,	ind = 0
		,	indJ = 0
		,	baseIndJ = 0
		,	newValArr = []
		,	arrToPush
		,	tempVal
		,	columnNamesArr = []
		,	rowNamesArr = []
		;
		// rotate data in chart, for standart view, and no rotate - for "rotated view"
		if(!isSwitchRowsAndColumns) {
			tableValues = this.rotateData(tableValues);
		}

		if(isUseFirstColumn) {
			baseIndJ = 1;
		}
		if(isUseFirstRow) {
			ind = 1;
		}

		if(tableValues && tableValues.length) {
			// prepare array
			for(ind; ind < tableValues.length; ind++) {
				// fill column headers
				if(isUseFirstRow) {
					if(ind == 0 && isUseFirstColumn) {
					} else {
						// you can't use first row like strings for correct graph calc (with current configuration)
						tempVal = parseFloat(tableValues[ind][0]);
						// use for string values
						// columnNamesArr.push(tableValues[ind][0]);
						columnNamesArr.push(tempVal);
					}
				}
				//
				newValArr = [];
				if(tableValues[ind] && tableValues[ind].length) {
					for(indJ = baseIndJ; indJ < tableValues[ind].length; indJ++) {
						// fill row headers
						if(ind == 1 && isUseFirstColumn) {
							rowNamesArr.push(tableValues[0][indJ]);
						}
						// fill values
						newValArr.push(parseFloat(tableValues[ind][indJ]));
					}
				}
				arrToPush = {};
				arrToPush['values'] = newValArr;
				if(isUseFirstRow) {
					arrToPush['text'] = tableValues[ind][0];
				}
				tblAssArr.push(arrToPush);
			}
		}
		return {
			'chartData': tblAssArr,
			'columnNameArr': columnNamesArr,
			'rowNameArr': rowNamesArr,
		};
	});
	/***********************************************************/
	var isStbGoogleInit = false;

	function drawChart(range, options, chartId, canvasId) {
		try {
			options = options || {};

			var selectedRangeData = $.extend(true, [], range.data)
			,	$currCanvas = $('#' + canvasId)
			,	chartType = getChartType();

			$currCanvas.html('');
			chartCreateData.table_id = range.table_id;
			chartCreateData.type = chartId;
			chartCreateData.options = options;
			chartCreateData.params = collectChartParams();
			chartCreateData.selection = range.selection;
			chartCreateData.unselected = range.unselected;

			if(chartType == 'google') {
				var googleChart = new stbGoogleChart()
				,	preparedData = googleChart.prepareChartData(selectedRangeData, chartId)
				;
				// init google charts, when no charts in admin
				if(!isStbGoogleInit) {
					google.charts.load('current', {packages: ['corechart']});
					google.charts.setOnLoadCallback(function() {
						googleChart.drawChart(preparedData, options, chartId, canvasId);
					});
					isStbGoogleInit = true;
				} else {
					googleChart.drawChart(preparedData, options, chartId, canvasId);
				}

				chartCreateData.rangeData = preparedData;
				chartCreateData.linesCount = selectedRangeData;
				delete chartCreateData.chartConfig;
			} else if(chartType == 'zing') {
				var zingChart = new stbZingChart()
				,	chartData = zingChart.prepareChartData(selectedRangeData, chartId, options);
				$('#' + canvasId).zingchart(chartData);

				chartCreateData.rangeData = selectedRangeData;
				chartCreateData.linesCount = selectedRangeData;
				chartCreateData.chartConfig = chartData;
			}
		} catch(e) {
			throw new Error('Can not build chart by its data. ' + e);
		}
	}

	function drawPreviewChart(canvasIdStr) {
		canvasIdStr = canvasIdStr || 'diagram';

		try {
			var range = getSelectedRangeData(false, true, canvasIdStr)
			,	chartId = getChartId();

			if(range.data == false) {
				$previewDialog.dialog('close');
				return;
			}

			if (chartId) {
				var showChartOptions = $('.PieChart, .LineChart, .BarChart, .ColumnChart, .BarChart3d, .DonutChart3d, .PieChart3d, .PyramidChart3d'),
					hideForChartOptions = $('.hideForPieChart, .hideForBubbleChart');

				showChartOptions.show();
				showChartOptions.not('.' + chartId).hide();
				hideForChartOptions.hide();
				hideForChartOptions.not('.hideFor' + chartId).show();
				drawChart(range, collectChartOptions(), chartId, canvasIdStr);
				if (jQuery("#diagram").find('[id*="google-visualization-errors"]').length > 0) {
					var error = jQuery("#diagram").find('[id*="google-visualization-errors"]').html();
					jQuery("#diagram").html('');
					jQuery("#diagram").append(error);
				}
				drawColorPickers();
			}
		} catch(e) {
			alert(e);
			throw new Error(e);
		}
	}

	function collectChartParams() {
		var paramsData = {};
		$('#previewDiagramDialog [data-tab="#type"] input[type="checkbox"]').each(function() {
			var id = $(this).attr('id');
			if ($(this).prop('checked')) {
				paramsData[id] = $(this).val();
			} else {
				paramsData[id] = false;
			}
		});
		return paramsData;
	}

	function collectChartOptions() {
		var $settingsTab = $('#previewDiagramDialog [data-tab="#settings"]'),
			inititalStateHidden = false;

		if (!$settingsTab.hasClass('active')) {
			inititalStateHidden = true;
			$settingsTab.addClass('active');
		}
		var optionsData = $settingsTab.find(':input').filter(':visible').serializeJSON();

		if(typeof(optionsData.en_custom_colors) != 'undefined') {
			optionsData = $settingsTab.find(':input').filter(':visible, input[type="hidden"]').serializeJSON();
		}
		// #484
		if(optionsData.legend && optionsData.legend.position == 'left') {
			optionsData.targetAxisIndex = 1;
		}
		// fix for applying x axis format
		if(optionsData.hAxis && optionsData.hAxis.format == 'none') {
			delete optionsData.hAxis.format
		}
		// fix for applying y axis format
		if(optionsData.vAxis && optionsData.vAxis.format == 'none') {
			delete optionsData.vAxis.format
		}
		if(optionsData.pointShape) {
			if(optionsData.pointShape.type == 'star' || optionsData.pointShape.type == 'polygon') {
				optionsData.pointShape.sides = optionsData.pointShape.sides > 0 ? optionsData.pointShape.sides : 5;
			}
			if(optionsData.pointShape.type == 'star') {
				optionsData.pointShape.dent = optionsData.pointShape.dent > 0 ? optionsData.pointShape.dent : 5;
			}
		}
		if(inititalStateHidden) {
			$settingsTab.removeClass('active');
		}
		return optionsData;
	}

	function clearChartOptions() {
		var $settingsTab = $('#previewDiagramDialog [data-tab="#settings"]');

		$settingsTab.find('input').val('');
		$settingsTab.find('[data-def]').each(function() {
			$(this).val($(this).data('def').toString());
		});
		$settingsTab.find(':checkbox').prop('checked', false).iCheck('update');
		$settingsTab.find('.chartColors').hide();
		removeColorPickers();
		g_stbDiagramCurRange = null;
	}

	function getUnselected() {
		var unselectData = $('#previewDiagramDialog input[name="range"]').val(),
			unselected = {};

		if(unselectData) {
			var rows = [],
				cols = [],
				val;

			unselected = unselectData.split(',');

			for(var i = 0; i < unselected.length; i++) {
				if(unselected[i].match(/^\d+$/g) && !isNaN(unselected[i])) {
					val = unselected[i];
					rows.push(val.trim());
				} else if(unselected[i].match(/^[a-z]+$/gi)) {
					val = window.supsystic.Tables.Editor.Hot.plugin.utils.toNum(unselected[i]);
					if(!isNaN(val)) {
						val++;	// to get column number
						cols.push(val);
					}
				} else {
					if(unselected[i].indexOf('r') != -1) {
						val = unselected[i].replace('r', '');
						if(!isNaN(val)) {
							rows.push(val.trim());
						}
					}
					if(unselected[i].indexOf('c') != -1) {
						val = unselected[i].replace('c', '');
						if(!isNaN(val)) {
							cols.push(val.trim());
						}
					}
				}
			}
			unselected = { 'rows': rows, 'cols': cols };
		}
		return unselected;
	}

	function hasTableShortCodes() {
		var data = (g_stbPagination	? editor.getSourceDataPagination() : editor.getSourceData()),
			rowLength = data.length,
			colLength = data[0].length,
			begin;
		for (var i = 0; i < rowLength; i++) {
			for (var j = 0; j < colLength; j++) {
				begin = data[i][j].indexOf('[');
				if(begin > -1 && begin < data[i][j].indexOf(']')) {
					return true;
				}
			}
		}
		return false;
	}

	function hasTableDBSource() {
		return $('#table-source-database').is(':checked');
	}
	function getTablePreview() {
		return $('#supsystic-table-' + app.getParameterByName('id'));
	}

	function getRangeSelection(range) {
		if(typeof(range) == 'undefined') return false;
		var rangeArr = range.split(':');

		if(rangeArr.length != 2) return false;

		if(hasTableDBSource()) {
			if(rangeArr[0].length <= 1 || rangeArr[1].length <= 1) return false;

			var x1 = rangeArr[0].charAt(0).toUpperCase(),
				x2 = rangeArr[1].charAt(0).toUpperCase(),
				y1 = Number(rangeArr[0].substr(1)),
				y2 = Number(rangeArr[1].substr(1)),
				abc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
				d;

			if(isNaN(y1) || isNaN(y2) || y1 < 1 || y2 < 1) return false;
			y1--; y2 --;
			var x1 = abc.indexOf(x1),
				x2 = abc.indexOf(x2);
			if(x1 == -1 || x2 == -1) return false;

			if(x1 > x2) {
				d = x2;	x2 = x1; x1 = d;
				d = y2; y2 = y1; y1 = d;
			}
			if(y1 > y2) {
				d = y2; y2 = y1; y1 = d;
			}

			return {range: abc.charAt(x1) + String(y1+1) + ':' + abc.charAt(x2) + String(y2+1), from: {col: x1, row: y1}, to: {col: x2, row: y2}};

		} else {
			var utils = app.Editor.Hot.plugin.utils;

			if(utils.isCell(rangeArr[0].toString())) {
				var from = controlCellCoord(utils.cellCoords(rangeArr[0])),
					to = (rangeArr[1] && utils.isCell(rangeArr[1].toString()) ? controlCellCoord(utils.cellCoords(rangeArr[1])) : from);
				return {from: from, to: to};
			}
			return false;
		}
	}

	function getSelectedDBData(range, isDraw, param) {
		var selection = range;

		if(!selection) {
			selection = getRangeSelection($('#source-diagram-range').val());
			if(selection == false) {
				alert('Error in Range!');
				return false;
			}
			$('#source-diagram-range').val(selection.range);
		}

		var button = isDraw ? $('#source-diagram-create') : $('button.preview-diagram[data-diagram-id="' + param + '"]');

		app.createSpinner(button);

		app.request({
			module: 'tables',
			action: 'getRangeDBData'}, {
				dbName: $('#source-db-name').val(),
				dbTable: $('#source-db-table').val(),
				dbExternal: $('#source-db-external').val(),
				dbLogin: $('#source-db-login').val(),
				dbPassword: $('#source-db-password').val(),
				dbFields: $('#source-db-fileds').val(),
				dbSQL: $('#source-db-sql').val(),
				range: selection
		}).done(function(response) {
			if (response.success) {
				var selectedData = response.rangeData;
				g_stbDiagramCurRange = { table_id: app.getParameterByName('id'), data: selectedData, selection: selection, unselected: {}, dontRecalc: false};
				if(isDraw) {
					$previewDialog.dialog('open');
					drawPreviewChart(param);
				} else {
					previewRerender(param, true);
				}
			}
		}).fail(function (error) {
			alert('Error: ' + error);
		}).always(function () {
			app.deleteSpinner(button);
		});

		return true;
	}


	function getSelectedRangeData(range, isDraw, param) {
		if(!g_stbDiagramCurRange || g_stbDiagramCurRange.data == false) {
			g_stbDiagramCurRange = {data: false};
			if(hasTableDBSource()) {
				getSelectedDBData(range, isDraw, param);
				return g_stbDiagramCurRange;
			}
			var editor = app.Editor.Hot,
				selection = (range ? range : editor.getSelectedRangeLast());

			if (selection === undefined) {
				//noinspection ExceptionCaughtLocallyJS
				throw new Error('You must select at least one cell.');
			}
			var data = (g_stbPagination
					? editor.getSourceDataPagination(selection.from.row, selection.from.col, selection.to.row,  selection.to.col)
					: editor.getSourceData(selection.from.row, selection.from.col, selection.to.row,  selection.to.col)),
				selectedData = data.slice(0),
				curRow = (selection.from.row < selection.to.row ? selection.from.row : selection.to.row),
				curCol = (selection.from.col < selection.to.col ? selection.from.col : selection.to.col),
				firstCol = curCol,
				rowLength = selectedData.length,
				colLength = selectedData[0].length,
				unselected = getUnselected(),
				shortcodes = false,
				formulas = false,
				recalcData = [],
				cell,
				beginShortcode;

			for (var i = 0; i < rowLength; i++) {
				if(unselected.rows && toeInArray(i + 1, unselected.rows) != -1) {
					selectedData[i] = undefined;
				}
				for (var j = 0; j < colLength; j++) {
					if(selectedData[i]) {
						if(unselected.cols && toeInArray(j + 1, unselected.cols) != -1) {
							selectedData[i][j] = undefined;
						} else {
							cell = selectedData[i][j];
							if(typeof cell == 'string') {
								beginShortcode = cell.indexOf('[');
								if(beginShortcode > -1 && beginShortcode < cell.indexOf(']')) {
									recalcData.push({i: i, j: j, x: curCol, y: curRow + 1});
									shortcodes = true;
								}
							}
							if(app.Models.Tables.isFormula(cell)) {
								selectedData[i][j] = app.Models.Tables.getFormulaResult(cell, curRow, curCol);
								recalcData.push({i: i, j: j, x: curCol, y: curRow + 1});
								formulas = true;
							}
						}
					}
					curCol++;
				}
				curRow++;
				curCol = firstCol;
			}
			selectedData = selectedData.filter(function(v){return v !== undefined});

			for(var r = 0; r < selectedData.length; r++) {
				selectedData[r] = selectedData[r].filter(function(v){return v !== undefined});
			}

			if(formulas && !shortcodes) {
				shortcodes = hasTableShortCodes();
			}

			if(shortcodes) {
				selectedData = replaceFromTablePreview(selectedData, recalcData);
			}
			g_stbDiagramCurRange = { table_id: app.getParameterByName('id'), data: selectedData, selection: selection, unselected: unselected, dontRecalc: (formulas && shortcodes) };
		}
		return g_stbDiagramCurRange;
	}

	function replaceFromTablePreview(data, recalcData) {
		var recalcLen = recalcData.length,
			$table = getTablePreview(),
			recalcObj,
			$td;

		if(recalcLen == 0) return data;

		if($table.length == 0)
		{
			alert('The table cells contain shortcodes, so you must precalculate the data first. To do this, click on Preview Tab.');
			return false;
		}

		for(var d = 0; d < recalcLen; d++) {
			recalcObj = recalcData[d];
			$td = $table.find('td[data-x="'+ recalcObj['x'] +'"][data-y="'+ recalcObj['y'] +'"]');
			if($td.length) {
				data[recalcObj['i']][recalcObj['j']] = $td.eq(0).data('original-value');
			}
		}
		return data;
	}

	var onAddDiagramClicked = function () {
		var cells = app.Editor.Hot.getSelectedRangeLast();
		if(cells) {
			if(cells['from']['col'] == cells['to']['col'] && cells['from']['row'] == cells['to']['row']) {
				alert('Select more cells.');
			} else {
				$previewDialog.dialog('open');
				drawPreviewChart();
			}
		} else {
			alert('You must select at least one cell.');
		}
	};

	var registerToolbarCallback = function (fn) {
		app.Editor.Tb.addMethod('addDiagram', fn);
		app.Editor.Tb.subscribe();
	};

	var createCanvas = function (id) {
		var $container = $('<div/>', {class: 'diagram supXs6'}),
			$shortcode = $('#shortcodeName'),
			$canvas = $('<div/>', {class: 'canvas'}),
			$info = $('<div/>', {class: 'info'}),
			utils = app.Editor.Hot.plugin.utils,
			range = chartCreateData.selection,
			from = utils.translateCellCoords({row: range.from.row, col: range.from.col}),
			to = utils.translateCellCoords({row: range.to.row, col: range.to.col});


		// Create DIV where we will draw diagram:
		$('<div/>', {id: 'diagram' + id, class: 'supsystic-table-diagram'}).attr('data-id', id).attr('data-chartdata', JSON.stringify(chartCreateData)).attr('data-charttype', getChartType()).appendTo($canvas);

		$('<div/>', {class:'range-diagram'})
			.append('<label>Range: </label>')
			.append($('<input/>', {id: 'diagram-range-id' + id, value: (from < to ? from + ':' + to : to + ':' + from), type:'text'}))
			.append($('<button/>', {class:'button preview-diagram', 'data-diagram-id': id})
				.append($('<i/>', {class:'fa fa-fw fa-eye'}))
					.on('click', function () {
						previewRerender(id);
					})
				)
			.append($('<button/>', {class:'button update-diagram'})
				.append($('<i/>', {class:'fa fa-floppy-o'}))
					.on('click', function () {
						updateDiagram(this, id);
					})
				)
			.append($('<button/>', {class:'button delete-diagram'})
				.append($('<i/>', {class:'fa fa-fw fa-trash-o'}))
					.on('click', function () {
						if (!confirm('Are you sure?')) {
							return;
						}
						deleteDiagram(id).done(function () {
							$container.remove();
						}).fail(function (err) {
							alert('Failed to remove diagram: ' + err);
						});
					})
				).appendTo($info);

		// Create layer with the shortcode:
		$('<div/>', {class:'shortcode'})
			.append(
			$('<input/>', {readonly:'readonly',type:'text'})
				.val(function () {
					return "["+ $shortcode.text() +" id='"+id+"']";
				})
				.on('click', function () {
					this.select();
				})
		).appendTo($info);

		$container
			.append($canvas)
			.append($info)
			.appendTo('#row-tab-diagrams');

		return $canvas.find('#diagram' + id);
	};

	var deleteDiagram = function (id) {
		return app.request({
			module: 'diagram',
			action: 'remove'
		}, {
			id: id
		});
	};

	function removeColorPickers(count) {
		count = count ? parseInt(count) : false;

		if(count) {
			$('.optionContainer.chartColors').find('.chartColorContainer').each(function() {
				if(count) {
					if($(this).is(':nth-last-child(' + count + ')')) {
						$(this).remove();
						--count;
					}
				}

			});
		} else {
			$('.optionContainer.chartColors').find('.chartColorContainer').each(function() {
				$(this).remove();
			});
		}

	}

	function currentColorPickersCount() {
		var i = 0;
		$('.optionContainer.chartColors').find('.chartColorContainer').each(function() {
			i++;
		});
		return i;
	}

	function drawColorPickers() {
		var chartType = getChartType(),
			chartDefColors = getGoogleChartDefColors(),
			existsColors = currentColorPickersCount(),
			chartId = getChartId(),
			totalColors = chartId == 'PieChart' ? chartCreateData.rangeData.length - 1 : chartCreateData.rangeData[0].length - 1;

		if(chartType == 'zing') {
			totalColors = chartCreateData.rangeData[0].length;
		}
		if(totalColors > existsColors) {
			var needToAdd = totalColors - existsColors;

			for(var i = 1; i <= needToAdd; i++) {
				var example = $('#chartColorContainerExample'),
					colorpicker = example.clone(),
					newId = 'chartColor_' + (existsColors + i - 1),
					color = typeof(chartDefColors[existsColors + i - 1]) != 'undefined' ? chartDefColors[existsColors + i - 1] : '#000000';

				colorpicker
					.attr('id', newId)
					.addClass('chartColorContainer')
					.appendTo(example.parents('.optionContainer.chartColors:first'));
				colorpicker.find('.chartColorArea').css('backgroundColor', color);
				colorpicker.find('input').attr('type', 'hidden').val(color);
				colorpicker.show();

				colorpicker.ColorPicker({
					color: color,
					onShow: function (colpkr) {
						$(colpkr).css('z-index', '9999999999999');
						$(colpkr).fadeIn(500);
						return false;
					},
					onHide: function (colpkr) {
						$(colpkr).fadeOut(500);
						return false;
					},
					onChange: function (hsb, hex, rgb) {
						var self = this;
						g_stbDiagramAxeColorLast = hex;

						if(!g_stbDiagramAxeColorTimeoutSet) {
							setTimeout(function(){
								g_stbDiagramAxeColorTimeoutSet = false;
								$(self).find('.colorpicker_submit').trigger('click');
							}, 500);
							g_stbDiagramAxeColorTimeoutSet = true;
						}
					},
					onSubmit: function(hsb, hex, rgb, el) {
						$(el).find('.chartColorArea').css('backgroundColor', '#' + g_stbDiagramAxeColorLast);
						$(el).find('input').val('#' + g_stbDiagramAxeColorLast);
						drawPreviewChart();
					}
				});
			}
		} else if(totalColors < existsColors) {
			var needToRemove = existsColors - totalColors;
			removeColorPickers(needToRemove)
		}
	}

	function initCharts() {
		$previewDialog = $('#previewDiagramDialog').dialog({
			autoOpen: false,
			width:    900,
			height:   'auto',
			modal:    true,
			close: function() {
				clearChartOptions();
			},
			buttons:  {
				Create: function (event) {
					$this = $(this);
					if (!getChartId()) {
						alert('Chart type is not selected');
						return;
					}
                    $this.parent().find('button').attr('disabled','disabled');

					if (g_stbDiagramCurRange && g_stbDiagramCurRange.dontRecalc && g_stbDiagramCurRange.dontRecalc == true) {
						chartCreateData.dontRecalc = 1;
					}
					app.request({
						module: 'diagram',
						action: 'save'
					}, {
						data: JSON.stringify(chartCreateData),
						table_id: app.getParameterByName('id')
					}).fail(function (error) {
                        $this.parent().find('button').removeAttr('disabled');
						alert('Failed to save diagram: ' + error);
					}).done(function (response) {
                        $this.parent().find('button').removeAttr('disabled');
						$('#row-tab-diagrams').find('.tutorial').hide();
						$('.button[href="#row-tab-diagrams"]').click();
						drawPreviewChart(createCanvas(response.id).attr('id'));
						$this.dialog('close');
					});
				},
				Cancel: function () {
					$(this).dialog('close');
				}
			}
		});

		registerToolbarCallback(onAddDiagramClicked);

		$('#previewDiagramDialog [data-tabs] a').on('click', function(event) {
			event.preventDefault();

			$('#previewDiagramDialog [data-tabs] a').removeClass('active');
			$(this).addClass('active');

			$('#previewDiagramDialog [data-tab]').removeClass('active');
			$('#previewDiagramDialog [data-tab="' + $(this).attr('href') + '"]').addClass('active');
		});

		$('#switchRowsColumns').on('change ifChanged', function(event) {
			$frSpan =  $('#useFirstRow').closest('label').find('span');
			$fcSpan = $('#useFirstColumn').closest('label').find('span');
			if ($(this).is(':checked')) {
				$frSpan.text($frSpan.text().replace('headers', 'labels'));
				$fcSpan.text($fcSpan.text().replace('labels', 'headers'));
			} else {
				$frSpan.text($frSpan.text().replace('labels', 'headers'));
				$fcSpan.text($fcSpan.text().replace('headers', 'labels'));
			}
		}).trigger('change');

		$('input[name="en_custom_colors"]').on('change ifChanged', function(event) {
			if ($(this).is(':checked')) {
				$('.optionContainer.chartColors').show();
			} else {
				$('.optionContainer.chartColors').hide()
			}
		});

		$('select[name="pointShape[type]"]').on('change', function() {
			var value = $(this).val();

			if(toeInArray(value, ['star', 'polygon']) != -1) {
				$('[name="pointShape[sides]"]').parent('.optionContainer').show();
			} else {
				$('[name="pointShape[sides]"]').parent('.optionContainer').hide();
			}
			if(toeInArray(value, ['star']) != -1) {
				$('[name="pointShape[dent]"]').parent('.optionContainer').show();
			} else {
				$('[name="pointShape[dent]"]').parent('.optionContainer').hide();
			}
		});

		$('.selectChartType .chart').on('click', function(event) {
			$('.selectChartType .chart').removeClass('active');
			$(this).addClass('active');
			drawPreviewChart();
		});

		$('#chartType, #previewDiagramDialog [data-tab="#settings"] :input').on('change ifChanged', function(event) {
			if(jQuery(this).attr('name') == 'range') {
				g_stbDiagramCurRange = null;
			}
			drawPreviewChart();
		});
		$('#switchRowsColumns, #useFirstRow, #useFirstColumn, #showLabelIntoDiagram').on('change ifChanged', function(event) {
			if($('.selectChartType .chart.active').length) {
				// Need to do it twice for normal work of custom colorpickers
				$('.selectChartType .chart.active').trigger('click');
				$('.selectChartType .chart.active').trigger('click');
			}
		});
	}

	function setRangesToInput() {
		var utils = app.Editor.Hot.plugin.utils;

		$('.supsystic-table-diagram').each(function () {
			var id = $(this).data('id')
			,	selection = $(this).data('chartdata').selection
			,	input = $('#diagram-range-id' + id);

			if(input && selection) {
				var from = utils.translateCellCoords({row: selection.from.row, col: selection.from.col})
				,	to = utils.translateCellCoords({row: selection.to.row, col: selection.to.col});

				$(input).val(from < to ? from + ':' + to : to + ':' + from);
			}
		});
	}
	function controlCellCoord(coord) {
		var editor = app.Editor.Hot,
			countRows = (g_stbPagination ? editor.bufferData.length : editor.countRows()),
			countCols = (g_stbPagination ? editor.bufferCols : editor.countCols());

		if(coord.row < 0) {
			coord.row = 0
		} else if(coord.row >= countRows) {
			coord.row = countRows - 1;
		}
		if(coord.col < 0) {
			coord.col = 0
		} else if(coord.col >= countCols) {
			coord.col = countCols - 1;
		}
		return coord;
	}

	function getChartId() {
		return $('.selectChartType .chart.active .chart-container').attr('id');
	}

	function getChartType() {
		return $('.selectChartType .chart.active .chart-container').attr('data-chart-type');
	}

	function previewRerender(chartId, loaded) {
		var selection = getRangeSelection($('#diagram-range-id' + chartId).val()),
			charts = $('.supsystic-table-diagram');

		if(selection == false) {
			alert('Error in Range!');
			return false;
		}

		for (var i = 0; i < charts.length; i++) {
			var chart = $(charts).eq(i);

			if(chart.data('id') == chartId) {
				var chartData = chart.data('chartdata'),
					chartType = chart.data('charttype'),
					htmlId = chart.attr('id'),
					options = chartData.params;

				chartRerenderParams.needRerender = true;
				chartRerenderParams.switchRowsColumns = options.switchRowsColumns,
				chartRerenderParams.useFirstColumn = options.useFirstColumn,
				chartRerenderParams.useFirstRow = options.useFirstRow,
        chartRerenderParams.showLabelIntoDiagram = options.showLabelIntoDiagram,

				chartData.selection.from = selection.from;
				chartData.selection.to = selection.to;
				if(typeof(loaded) == 'undefined' || !loaded) {
					g_stbDiagramCurRange = null;
				}

				var selectionData = getSelectedRangeData(chartData.selection, false, chartId).data;
				if(selectionData === false) return;

				var	selectedRangeData = $.extend(true, [], selectionData);

				if(chartType == 'google') {
					var googleChart = new stbGoogleChart(),
						preparedData = googleChart.prepareChartData(selectedRangeData, chartData.type);

					chartData.rangeData = preparedData;
					chartData.linesCount = selectedRangeData;
					//googleChartRender(params, i);
					data = new google.visualization.arrayToDataTable(chartData.rangeData);
					googleChart = new google.visualization[chartData.type](document.getElementById(htmlId));
					googleChart.draw(data, chartData.options);
					//googleChart.drawChart(chartData.rangeData, chartData.options, chartData.type, htmlId);

				} else if(chartType == 'zing') {
					var zingChart = new stbZingChart(),
						chartConfig = zingChart.prepareChartData(selectedRangeData, chartData.type, chartData.options);
					$('#' + htmlId).zingchart(chartConfig);

					chartData.rangeData = selectedRangeData;
					chartData.linesCount = selectedRangeData;
					chartData.chartConfig = chartConfig;
				}
				chartRerenderParams.needRerender = false;
				delete chartData.dontRecalc;
				if (g_stbDiagramCurRange && g_stbDiagramCurRange.dontRecalc && g_stbDiagramCurRange.dontRecalc == true) {
					chartData.dontRecalc = 1;
				}
				rerenderedCharts[chartId] = $.extend(true, {}, chartData);
				break;
			}
		}
	}

	function updateDiagram(btn, id) {
		var	icon = $(btn).find('i'),
			bntPreview = $(btn).parent().find('button.preview-diagram'),
			btnDelete = $(btn).parent().find('.delete-diagram');

		if(id in rerenderedCharts) {
			$(icon).attr('class', 'fa fa-spinner fa-spin');
			$(bntPreview).attr('disabled', true);
			$(btnDelete).attr('disabled', true);
			app.request({
				module: 'diagram',
				action: 'update'
			}, {
				data: JSON.stringify(rerenderedCharts[id]),
				id: id
			}).fail(function (error) {
				alert('Failed to save diagram: ' + error);
			}).always(function (response) {
				$(icon).attr('class', 'fa fa-floppy-o');
				$(bntPreview).attr('disabled', false);
				$(btnDelete).attr('disabled', false);
			});
		} else {
			alert('First you need to do a chart Preview');
		}
	}

	$(document).ready(function () {
		var tablesModel = app.Models.Tables,
			formSettings = $('form#settings');

		chartRerenderParams.needRerender = false;

		setRangesToInput();

		$('#openEditorTab').on('click', function(event) {
			event.preventDefault();
			jQuery('.tabs-wrapper a[href="#row-tab-editor"]').trigger('click');
		});

		initCharts();

		$('button.preview-diagram').on('click', function () {
			previewRerender($(this).attr('data-diagram-id'));
		});

		$('.update-diagram').on('click', function () {
			updateDiagram(this, $(this).attr('data-diagram-id'));
		});

		$('.delete-diagram').on('click', function () {
			if (!confirm('Are you sure?')) {
				return;
			}
			var $btn = $(this);

			deleteDiagram($btn.attr('data-diagram-id')).done(function () {
				$btn.parents('.prerendered-diagram').remove();
			}).fail(function (err) {
				alert('Failed to remove diagram: ' + err);
			});
		});

		formSettings.find('[name="numberFormat"]').on('change', function(e) {
			e.preventDefault();
			var value = $.trim($(this).val());
			tablesModel._setFormatToDiagramsAxis(value, 'number');
		});

		// Set currency
		formSettings.find('[name="currencyFormat"]').on('change', function(e) {
			e.preventDefault();
			var value = $.trim($(this).val());
			tablesModel._setFormatToDiagramsAxis(value, 'currency');
		});

		// Set percent
		formSettings.find('[name="percentFormat"]').on('change', function(e) {
			e.preventDefault();
			var value = $.trim($(this).val());
			tablesModel._setFormatToDiagramsAxis(value, 'percent');

		});

		$('#source-diagram-create').on('click', function(event) {
			event.preventDefault();
			if($('#table-source-database').is(':checked')) {
				if($('#source-diagram-range').val() != '') {
					g_stbDiagramCurRange = null;
					drawPreviewChart();
				} else {
					alert('Range is required.');
				}
			}
			return false;
		});

		$('[href="#row-tab-diagrams"]').on('click',function(){
			setTimeout(function(){
                $('#row-tab-diagrams').find('.preview-diagram').click();
			},200);
		});
	});
}(window.jQuery, window.supsystic.Tables));
