(function(){
	"use strict";
	var job = $('#global-job-number').data('job');
	var layoutUrl = '/offlinepage/' + job + '/layout.json';
	var activeControls = {};

	$.getJSON( layoutUrl, function(data) {
		renderTabPanel( data );
	});

	function getObjectValueByPartialName(obj, name){
        if (typeof obj !== "object") {
            throw new Error("object is required!");
        }
        for (var prop in obj) {
            if (prop.indexOf(name) === 0){
                return obj[prop];
            }
        }
        return undefined;
    }


	function renderTabPanel( layoutData ) {
		var tabTemplate = _.template($('#tabTemplate').text()),
		panelTemplate = _.template($('#panelTemplate').text());

		var defaults;
		try {
			defaults = JSON.parse('{"' + decodeURI(window.location.hash.substr(1)).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"') + '"}');
		} catch(e) {
			defaults = {
				tab : layoutData[0].name.replace(/</g, "&lt;").replace(/>/g, "&gt;")
			};
		}
		activeControls = defaults;

		var tabs = [];
		layoutData.map(function(tab) {
			tabs.push(tab.name)
		});
        // просмотр чужого пользовательского отчета (которого нет в layout текущего пользователя), например если кто-то поделился ссылкой.
		if (defaults.tab && tabs.indexOf(defaults.tab) === -1) {
			$.ajax({
					url : '/offlinepage/' + job + '/custom_report.json?cur=' + defaults.tab.split("__")[1],
					type : 'GET',
					dataType : 'json',
                async: false
            }).success(function (controls) {
						layoutData.push(controls)
            })
		}

		$('.job-tabpanel__krutilka').remove();
		$.each( layoutData, function( i ) {
			var tab = layoutData[i];
			$('#job-tabpanel__tabs').append(tabTemplate({tab: tab.name.replace(/</g, "&lt;").replace(/>/g, "&gt;"), title: tab.title.replace(/</g, "&lt;").replace(/>/g, "&gt;")}));
			$('#job-tabpanel__panels').append(panelTemplate({tab: tab.name.replace(/</g, "&lt;").replace(/>/g, "&gt;"), title: tab.title.replace(/</g, "&lt;").replace(/>/g, "&gt;")}));
		});

		var customToggleTemplate = _.template($('#customToggleTemplate').text());
        var $curToggleTab = $('#cur-toggle-tab');
		$('#job-tabpanel__tabs').append(customToggleTemplate({}));
		var $curContents = $('#cur-contents');
		$curContents.load('/offlinepage/render_custom_report_form?job='+job);
		$curContents.css('position', 'fixed');
		$curContents.css('left', 15);
		$('#cur-toggle-tab').on('shown.bs.dropdown', function () {
			$('#cur-toggle').css('z-index', 1001);
			$('#cur_name').focus()
		});
		$('#cur-toggle-tab').on('hidden.bs.dropdown', function () {
			$('#cur-toggle').css('z-index', 0)
		});

		$('#job-tabpanel__panels').append();

		$('.nav-tabs a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
			activeControls.tab = $(this).data('tab');
			window.location.hash = $.param(activeControls);
			var controls = _.findWhere(layoutData, {name: $(this).data('tab')}).controls;
			renderPanel( $(this).data('tab'), controls );
		});

		$('.delete-custom-report').on('click', function(event) {
			var id = $(this).data('id'),
			title = $(this).data('title');
			if (confirm('Удалить пользовательский отчет '+title)) {
				$.get("/api/delete_custom_report?id="+id);
				$("li#job-tabpanel__tab__custom__"+id).remove();
				$('div#job-tabpanel__panel__custom__'+id).remove();
				if (activeControls.tab === 'custom__'+id) {
					activeControls.tab = layoutData[0].name.replace(/</g, "&lt;").replace(/>/g, "&gt;");
					window.location.hash = $.param(activeControls);
					$('.nav-tabs a[href="#job-tabpanel__panel__' + layoutData[0].name.replace(/</g, "&lt;").replace(/>/g, "&gt;") + '"]').tab('show');
				}
			}

			event.preventDefault();
		});

		$('.nav-tabs a[href="#job-tabpanel__panel__' + defaults['tab'] + '"]').tab('show');
    }
    function renderPanel( tab, controls ) {
		if ($('#job-tabpanel__panel__'+tab).html().trim() === '') {
			var slider = _.findWhere(controls, {name: 'slider'});
	    	var plot_groups = _.findWhere(controls, {name: 'plot_groups'});
	    	var tags =  _.findWhere(controls, {name: 'tags'});
			var machines = _.findWhere(controls, {name: 'machines'});
			var metrics = _.findWhere(controls, {name: 'metrics'});
			var mobile = _.findWhere(controls, {name: 'mobile'});

			// Ищем настройки

            var activeMachine,
                activeMetrics,
                activeTag,
                activePlotGroup,
                activeMobile;

			if (machines) {
				activeMachine = machines['default'].toString()
			}
			else {
				activeMachine = ''
			}
			if (metrics) {
				activeMetrics = metrics['default']
			}
			else {
				activeMetrics = ''
			}
			if (tags) {
				activeTag = tags['default']
			}
			else {
				activeTag = ''
			}
			if (plot_groups) {
				activePlotGroup = plot_groups['default']
			}
			else {
				activePlotGroup = ''
			}
			if (mobile) {
				activeMobile = mobile['default']
			}
			else {
				activeMobile = ''
			}

			var parsedHash;
			try {
				parsedHash = JSON.parse('{"' + decodeURI(window.location.hash.substr(1)).replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"') + '"}');
			} catch(e) {
				parsedHash = {
						tab: tab,
						tags: activeTag,
						plot_groups: activePlotGroup,
						machines: activeMachine,
						metrics: activeMetrics,
                        mobile: activeMobile,
				};
			}
			parsedHash.tab = tab;

			if (!('tags' in parsedHash)){
				parsedHash.tags = activeTag;
            }
            if (!('plot_groups' in parsedHash)){
				parsedHash.plot_groups = activePlotGroup;
            }
            if (!parsedHash.machines) {
				if (machines) {
					activeMachine = machines['default'].toString()
				}
				else {
					activeMachine = ''
				}
				parsedHash.machines = activeMachine
            }
            if (!('metrics' in parsedHash)){
				parsedHash.metrics = activeMetrics
            }
            parsedHash.mobile = activeMobile;
            if (!('slider_start' in activeControls) && !('slider_start' in parsedHash)) {
				parsedHash.slider_start = slider.start
			} else if (!('slider_start' in parsedHash) && ('slider_start' in activeControls)) {
				parsedHash.slider_start = activeControls.slider_start
            }
			if (!('slider_end' in activeControls) && !('slider_end' in parsedHash)) {
				parsedHash.slider_end = slider.end
			} else if (!('slider_end' in parsedHash) && ('slider_end' in activeControls)) {
				parsedHash.slider_end = activeControls.slider_end
            }
			activeControls = parsedHash;
			window.location.hash = $.param(activeControls);

			// Рендерим все, что нужно

			renderSlider( slider );

			if (plot_groups && tab.split('__')[0] !== 'custom') {
				renderControls( plot_groups )
			}
			else {
				activeControls.plot_groups = 'main'
			}
			if (tags) {
				renderControls( tags )
			}
			if (machines) {
				renderControls( machines )
			}
			if (metrics) {
				renderControls( metrics )
			}
			if (mobile) {
				renderControls( mobile )
			}

			var plotsContainerTemplate = _.template($('#plotsContainerTemplate').text());
			$('#job-tabpanel__panel__'+tab).append(plotsContainerTemplate({tab: tab}));
			loadPlots()
		}
    }
    // TODO: Глобальный ползунок!
	function renderSlider( slider ) {
        moment.locale('ru');
		var sliderTemplate = _.template($('#sliderTemplate').text());
		$('#job-tabpanel__panel__'+activeControls.tab).append(sliderTemplate({tab: activeControls.tab, slider: slider}));
		$('#job-controls__slider__'+activeControls.tab).ionRangeSlider({
			type: "double",
			min: moment(slider.min * 1000, "x"),
			max: moment(slider.max * 1000, "x"),
            from: moment(parseInt(activeControls.slider_start) * 1000, "x"),
            to: moment(parseInt(activeControls.slider_end) * 1000, "x"),
			hide_min_max: true,
		    hide_from_to: false,
		    grid: true,
		    prettify: function (num) {
		        var m = moment(num, "x");
		        return m.format("D MMM HH:mm:ss");
		    },
		    onChange: function (values) {
		        $(".irs-min").text(moment(values.from, "x").format("D MMM HH:mm:ss"));
		        $(".irs-max").text(moment(values.to, "x").format("D MMM HH:mm:ss"));
		        $("#job-controls__slider-submit__"+activeControls.tab).unbind();
		        var currentControls = slider;
		        currentControls["start"] = Math.floor(values.from/1000);
		        currentControls["end"] = Math.floor(values.to/1000);
		        $("#job-controls__slider-submit__"+activeControls.tab).data('from', Math.floor(values.from/1000));
		        $("#job-controls__slider-submit__"+activeControls.tab).data('to', Math.floor(values.to/1000));
		        $("#job-controls__slider-submit__"+activeControls.tab).bind('click', function(event){
					submitSlider($(this).data())
				});
		    },
		});
		var sliderObj = $('#job-controls__slider__'+activeControls.tab).data("ionRangeSlider");
		sliderObj.update({
            'from': moment(parseInt(activeControls.slider_start) * 1000, 'x'),
            'to': moment(parseInt(activeControls.slider_end) * 1000, 'x'),
		});


		$("#job-controls__slider-submit__"+activeControls.tab).bind('click', function(event){
			submitSlider($(this).data());
			event.preventDefault();
		});
		function submitSlider(slider) {
			activeControls.slider_start = slider.from;
			activeControls.slider_end = slider.to;
			window.location.hash = $.param(activeControls);
			loadPlots();
		}

		var helpersTemplate = _.template($('#helpersTemplate').text());
		var helperTemplate = _.template($('#helperTemplate').text());
        $('#job-tabpanel__panel__'+activeControls.tab).append(helpersTemplate({tab: activeControls.tab}));

		slider.helpers.map(function(helper) {
			$('#job-controls__group__'+activeControls.tab+'__slider_helpers').append(helperTemplate(helper))
		});
		$('#job-controls__group__'+activeControls.tab+'__slider_helpers li').on('click', function(event) {
			$('#job-controls__group__'+activeControls.tab+'__slider_helpers .active').removeClass('active');
			$(this).children().addClass('active');
			var sliderObj = $('#job-controls__slider__'+activeControls.tab).data("ionRangeSlider");
			sliderObj.update({
                'from': moment($(this).data('start') * 1000, 'x'),
                'to': moment($(this).data('end') * 1000, 'x'),
			});
            var $sliderSubmit = $("#job-controls__slider-submit__" + activeControls.tab);
            $sliderSubmit.data('from', $(this).data('start'));
            $sliderSubmit.data('to', $(this).data('end'));
		    activeControls.slider_start = $(this).data('start');
			activeControls.slider_end = $(this).data('end');
		    window.location.hash = $.param(activeControls);
		    loadPlots();
		    event.preventDefault();
		})
    }
    function renderControls( controls ) {
		var controlsTemplate = _.template($('#controlsTemplate').text()),
		buttonTemplate = _.template($('#buttonTemplate').text());
		$('#job-tabpanel__panel__'+activeControls.tab).append(controlsTemplate({tab: activeControls.tab, name: controls.name}));
		_.each(controls.values, function(button) {
			if (controls.name === 'machines') {
				var button_title = button[2] ? button[2] : button[1];
				$('#job-controls__group__'+activeControls.tab+'__'+controls.name).append(buttonTemplate({tab: activeControls.tab, button_name: button[0], button_title: button_title, controls_name: controls.name}))
			}
			else {
				$('#job-controls__group__'+activeControls.tab+'__'+controls.name).append(buttonTemplate({tab: activeControls.tab, button_name: button[0], button_title: button[1], controls_name: controls.name}))
			}
		});
		activateControls( controls )
    }
    function activateControls( controls ) {
		if (controls.name === 'tags') {
			$('#job-controls__group__'+activeControls.tab+'__'+controls.name).find('button[data-val="'+activeControls.tags+'"]').addClass('active')
		}
		if (controls.name === 'machines') {
			$('#job-controls__group__'+activeControls.tab+'__'+controls.name).find('button[data-val="'+activeControls.machines+'"]').addClass('active')
		}
		if (controls.name === 'metrics') {
			$('#job-controls__group__'+activeControls.tab+'__'+controls.name).find('button[data-val="'+activeControls.metrics+'"]').addClass('active')
		}
		if (controls.name === 'mobile') {
			$('#job-controls__group__'+activeControls.tab+'__'+controls.name).find('button[data-val="'+activeControls.mobile+'"]').addClass('active')
		}
		if (controls.name === 'plot_groups') {
			$('#job-controls__group__'+activeControls.tab+'__'+controls.name).find('button[data-val="'+activeControls.plot_groups+'"]').addClass('active')
		}
		$('#job-controls__group__'+activeControls.tab+'__'+controls.name).find('button').off();
		$('#job-controls__group__'+activeControls.tab+'__'+controls.name).find('button').on('click', function(event) {
			$('#job-controls__group__'+activeControls.tab+'__'+$(this).data('control')).find('button').removeClass('active');
			activeControls[$(this).data('control')] = $(this).data('val');
			window.location.hash = $.param(activeControls);
			loadPlots();
			event.preventDefault();
		});
    }
    function loadPlots() {
		var parsedHash = JSON.parse('{"' + decodeURI(window.location.hash.substr(1)).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"') + '"}');
		activeControls = parsedHash;
		$('#b-lunapark-offlinepage__charts__'+activeControls.tab).html('');
		$.ajax({
            method: 'GET',
            url: '/offlinepage/'+job+'/plots_to_show.json?' + $.param(activeControls),
            dataType: 'json',
            success: function(data) {
            	activeControls.compress_ratio = data['compress_ratio'];
            	var plotTemplate = _.template($('#plotTemplate').text());
            	_.each(data['plots'], function(plotType) {
            		$('#b-lunapark-offlinepage__charts__'+activeControls.tab).append(plotTemplate({tab: activeControls.tab, plot_type: plotType.split('@')[0].replace(':','__'), host:plotType.split('@')[1] || ''}));
            		getData(plotType)

            	});
    		$('#job-plots__compress-ratio__'+activeControls.tab).text(data['compress_ratio'] + ' sec. per dot');
            },
		});
    }
    function getData(plotType) {

        var host = plotType.split('@')[1] || '',
		plotType = plotType.split('@')[0];

		function clone(obj) {
		    if (null === obj || "object" !== typeof obj) return obj;
		    var copy = obj.constructor();
		    for (var attr in obj) {
		        if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
		    }
		    return copy;
		}
		var params = clone(activeControls); // чтобы не добавлять кал в общие настройки.
		params.plot_type = plotType;
		params.machines = host;
        plotType = plotType.replace(':', '__').replace('(', '').replace(')', '');
		var url = '/offlinepage/' + job + '/plot_data.json?' + $.param(params);

		var container = $('#job-plots__'+activeControls.tab+'__'+plotType+host);

		$.ajax({
			url : url,
			type : 'GET',
			dataType : 'json',
			success : function(data) {
				if (data === null) {
					var noDataTemplate = _.template($('#noDataTemplate').text());
					container.addClass('job-plots__highcharts');
					//container.css('height', '400px')
					container.html(noDataTemplate({plotType: plotType, host: container.data('host')}))
				}
				else {
					if ( typeof data === 'string') {
						data = JSON.parse(data);
					}
					if (data.table) {
						if (plotType.endsWith('_table') && activeControls.plot_groups === 'tables') {
							container.removeClass('col-xl-6');
							container.addClass('col-xl-12');
							_drawTable(data, plotType, host);
						} else if (plotType === 'monitoring_aggregates_table') {
						    container.removeClass('col-xl-6');
							container.addClass('col-xl-12');
							_drawTable(data, plotType, host);
                        } else {
							_drawTable(data, plotType, host);
						}
					} else {
						_draw(data, plotType, host);
					}
				}
			}
		})
    }
    function _drawTable(data, plotType, host) {
		var container = $('#job-plots__'+activeControls.tab+'__'+plotType+host);
		container.addClass('job-plots__table');
		container.html('');

		var title = $('<h4>' + data.title + '</h4>').appendTo(container);
		var table = $('<table class="table table-sm table-striped table-hover" style="margin-bottom: 2rem;"><thead><tr id="table_header__'+activeControls.tab+'__'+plotType+host+'"></tr></thead><tbody></tbody></table>'); //style="font-family: Monaco, Monospace, Courier;"
		var data = data.data;

		container.closest('.job-plots__container').css({
			'height' : 'auto',
			//'font-size' : '120%',
			//'text-align' : 'center'
		});

		data.columns.map(function(col) {
			col.values.map(function(cell, pos) {
                var valueText;
				if (cell && data.columns.indexOf(col) > 0 && cell.toString().indexOf(".") > 0) {
					cell = cell.toString().replace('\%', ' \%');
					var fraction = cell.split('.')[1].split(' ')[0];
					while (fraction && fraction.length < 3) {
						fraction = fraction + '0'
					}
                    valueText = cell.split('.')[0] + '.<span style="font-size:80%; opacity: 0.7;">' + fraction + '</span>';
					if (cell.split('.')[1].indexOf(" ") > 0) {
						valueText += ' ' + cell.split('.')[1].split(' ')[1]
					}
				}
				else {
                    valueText = cell.toString().replace(/</g, "&lt;").replace(/>/g, "&gt;")
				}

				var text = valueText || cell, weight = cell.weight || col.weight || 'normal',
				align = cell.align || col.align || 'left',
				color = cell.color || col.color || '#333',
				cell = $('<td style="text-align: ' + align + '; font-weight: ' + weight + '; color: ' + color + '">' + text + '</td>'),
				row = table[0].tBodies[0].rows[pos];
				if (!row) {
					row = table[0].tBodies[0].insertRow(-1);
				}
				cell.appendTo(row);
			});
		});

		table.appendTo(container);

		data.header.map(function(th) {
			$('tr#table_header__'+activeControls.tab+'__'+plotType+host).append($('<th style="text-align:right;">'+th+'</th>'))
		});
    }
    function _draw(data, plotType, host) {// draw chart
        var container = $('#job-plots__' + activeControls.tab + '__' + plotType.replace('(', '').replace(')', '') + host);
		if (data.x.type === 'datetime') {
			container.addClass('job-plots__highcharts__timeline')
		}
		container.addClass('job-plots__highcharts');
		Highcharts.setOptions({ // This is for all plots, change Date axis to local timezone
            global : {
                useUTC : false
            }
        });

		var xValues = ($.isArray(data.x.values) ? data.x.values : data.data[data.x.values]),
		xType = data.overrides && data.overrides.xAxis && data.overrides.xAxis.type || data.x.type || 'datetime',
		isDateTime = xType === 'datetime';
		var hideOnDone = [], overrides = {
			title : {
				text : data.title
			},
			subtitle : {
				text : data.subtitle
			},
			chart: {
                renderTo: 'job-plots__' + activeControls.tab + '__' + plotType.replace('(', '').replace(')', '') + host,
				resetZoomButton: {
	                theme: {
	                    fill: 'white',
	                    stroke: 'silver',
	                    r: 0,
	                    states: {
	                        hover: {
	                            fill: '#41739D',
	                            style: {
	                                color: 'white',
	                            }
	                        }
	                    }
	                },
	                relativeTo: 'chart',
	            },
                events: {
					click: function(event) {
						Highcharts.Pointer.prototype.reset = function () {}; // disable tooltip disappearing
						showAllCrosshairs(event, container);
						var ST = '\
							top: -'+container.height()+'px; \
							height: '+container.height()+'px; \
							margin-bottom: -'+container.height() +'px; \
							z-index: 99; \
							position: relative; \
							background-color: rgba(255,255,255,0);';
						$('.job-plots__highcharts__timeline').each(function() {
							$(this).append('<div class="blocker" style="'+ST+'">\
									<span class="fa fa-lock" style="position: absolute; padding: 5px; color: gray; opacity: 0.3; font-size: 24px;"></span>\
									</div>')
						});
						var $blocker = $('.blocker');
						$blocker.off();
						$blocker.on('click', function(event) {
							Highcharts.Pointer.prototype.reset = tooltipReset; // reenable tooltip disappearing
							hideAllCrosshairs(event);
							$('.blocker').remove();
							event.stopPropagation();
						});
					}
				},
			},
			xAxis : {
				dateTimeLabelFormats : {
					second : "%H:%M:%S"
				},
                labels: {
                	overflow: 'justify',
                },
                events: {
                    setExtremes: syncExtremes,
                },
				endOnTick : false,
				showFirstLabel : true,
				showLastLabel : true,
				startOnTick : false,
				type : xType
			},
			tooltip: {
				formatter: function () {
                    var res = '';
                    if (isDateTime) {
                        var formattedTime = moment.unix(this.x / 1000).format("HH:mm:ss");
                        res += '<small style="font-size: 80%;">' + formattedTime + '</small><br>';
                    } else {
                        res += '<small style="font-size: 80%;">' + this.x + '</small><br>';
                    }
                    // formatting series values
                    res += '<table>';

                    if (this.points) {
                        $.each(this.points, function (i, point) {
                            var ser = '<tr><td><span style="color: ' + this.series.color + ';">' +
                                this.series.name.replace(/</g, "&lt;").replace(/>/g, "&gt;") +
                                '</span>' +
                                '<span> : </span></td>' +
                                '<td style="padding-top: 3px;">&emsp;<span style="font-weight: bold; color: #333;">' +
                                this.y.toString().split('.')[0].replace(/\B(?=(\d{3})+(?!\d))/g, "'") + // regexp: thousands delimiter
                                '</span>';
                            if (this.y.toString().indexOf(".") > 0) { // pretty fraction part
                                var fraction = this.y.toString().split('.')[1];
                                while (fraction && fraction.length < 3) {
                                    fraction = fraction + '0'
                                }
                                fraction = fraction.slice(0, 3);
                                ser += '<span style="font-size: 80%; font-weight: bold;">.' +
                                    fraction +
                                    '</span>'
                            }
                            ser += '</td></tr>';
                            res += ser
                        })
                    } else {
                        res += '<tr><td><span>' + this.point.text + '</span></td></tr>'
                    }
                    return res
                }
			},
			yAxis : [],
			series : []
		}, cfg = {};
		if (isDateTime) {
			xValues = xValues.map(function(ts) {
				return ts * 1000;
			});
		} else {
			overrides.xAxis.categories = xValues;
		}
		$.each(data.y, function(index) {
			var group = this, yAxis = {
				showFirstLabel : false,
				showLastLabel : false,
				labels : {
					formatter : function() {
						if (this.value) {
							return this.axis.defaultLabelFormatter.call(this) + ' ' + (group.label || '');
						}
						else {
							return '';
						}
					}
				},
				title : {
					text : 'TITLE',
				}
			};
			if (this.position === "right") {
				yAxis.opposite = true;
				yAxis.labels.align = 'right';
				yAxis.labels.x = -12;
				yAxis.labels.y = -4;
				//yAxis.gridLineWidth = 0;
			} else {
				yAxis.opposite = false;
				yAxis.labels.align = 'left';
				yAxis.labels.x = 12;
				yAxis.labels.y = -4;
				//yAxis.gridLineWidth = 0;
			}

			if (group.stacking) {
				overrides.plotOptions = {
					area : {
						stacking : group.stacking
					}
				};
			}

			group.graphs.map(function(graph) {
				var type = graph.type || group.type || 'area';
				var values = ($.isArray(graph.values) ? graph.values : data.data[graph.values]);
				if (isDateTime) {
					values = values.map(function(val, pos) {
						if (val instanceof Array) {
							return val
						} else {
							return xValues[pos] ? {
								x : xValues[pos],
								y : val
							} : null;
						}
					});
				}
				var serie = {
					name : graph.title || 'no title',
					color : graph.color,
					data : values,
					type : type,
					yAxis : overrides.yAxis.length
				};
				if ('zIndex' in graph) {
					serie.zIndex = graph.zIndex;
				}
				if (graph.disabled) {
					hideOnDone.push(serie.name);
				}
				if ('overrides' in graph) {
					serie = $.extend(true, serie, graph.overrides);
				}
				overrides.series.push(serie);
			});
			if (index === (data.y.length - 1)) {  // add events series only to last yAxis
			    if (getObjectValueByPartialName(data.data, '_user_events_') !== undefined) {
                    overrides.series.push(getObjectValueByPartialName(data.data, '_user_events_'));
                }
                if (getObjectValueByPartialName(data.data, '_tank_events_') !== undefined) {
                    overrides.series.push(getObjectValueByPartialName(data.data, '_tank_events_'));
                }
            }
            if ('overrides' in group) {
                yAxis = $.extend(true, yAxis, group.overrides);
            }
			overrides.yAxis.push(yAxis);
		});
		var defaults = _getDefaultConfig();
		cfg = $.extend(true, cfg, defaults, overrides, 'overrides' in data ? data.overrides : {});
		//console.log('cfg', cfg);
		var rendered = new Highcharts.Chart(cfg);

		/*$('#job-plots__'+activeControls.tab+'__'+plotType+host).append('<button class="btn btn-secondary btn-xs" style="cursor: default; position: relative; top: -'+(container.height()-8)+'px; margin-left: 5px;" id="exportButton__'+activeControls.tab+'__'+plotType+host+'">.png</button>')

		$('#exportButton__'+activeControls.tab+'__'+plotType+host).on('click', function () {
	        //var chart = $('#job-plots__'+activeControls.tab+'__'+plotType+host).highcharts();
	        rendered.exportChart();
	    });*/

	    if (hideOnDone.length) {
			rendered.series.map(function(serie) {
				if ($.inArray(serie.name, hideOnDone) !== -1) {
					serie.hide();
				}
			});
		}

	    container.chart = rendered;

	    /**
	     * Override the reset function, we don't need to hide the tooltips and crosshairs.
		 * Reset the tracking by hiding the tooltip, the hover series state and the hover point
		 *
		 * @param allowMove {Boolean} Instead of destroying the tooltip altogether, allow moving it if possible
		 */


	    var each = function(arr, fn, ctx) { // modern browsers
            return Array.prototype.forEach.call(arr, fn, ctx);
        };

		var tooltipReset = function(allowMove, delay) {
                var pointer = this,
                    chart = pointer.chart,
                    hoverSeries = chart.hoverSeries,
                    hoverPoint = chart.hoverPoint,
                    hoverPoints = chart.hoverPoints,
                    tooltip = chart.tooltip,
                    tooltipPoints = tooltip && tooltip.shared ? hoverPoints : hoverPoint;

                // Check if the points have moved outside the plot area (#1003, #4736, #5101)
                if (allowMove && tooltipPoints) {
                    each(splat(tooltipPoints), function(point) {
                        if (point.series.isCartesian && point.plotX === undefined) {
                            allowMove = false;
                        }
                    });
                }

                // Just move the tooltip, #349
                if (allowMove) {
                    if (tooltip && tooltipPoints) {
                        tooltip.refresh(tooltipPoints);
                        if (hoverPoint) { // #2500
                            hoverPoint.setState(hoverPoint.state, true);
                            each(chart.axes, function(axis) {
                                if (axis.crosshair) {
                                    axis.drawCrosshair(null, hoverPoint);
                                }
                            });
                        }
                    }

                    // Full reset
                } else {

                    if (hoverPoint) {
                        hoverPoint.onMouseOut();
                    }

                    if (hoverPoints) {
                        each(hoverPoints, function(point) {
                            point.setState();
                        });
                    }

                    if (hoverSeries) {
                        hoverSeries.onMouseOut();
                    }

                    if (tooltip) {
                        tooltip.hide(delay);
                    }

                    if (pointer.unDocMouseMove) {
                        pointer.unDocMouseMove = pointer.unDocMouseMove();
                    }

                    // Remove crosshairs
                    each(chart.axes, function(axis) {
                        axis.hideCrosshair();
                    });

                    pointer.hoverX = pointer.prevKDPoint = chart.hoverPoints = chart.hoverPoint = null;
                }
            };


	    /**
	     * Synchronize zooming through the setExtremes event handler.
	     */
	    function syncExtremes(e) {
	        var thisChart = this.chart;

	        if (e.trigger !== 'syncExtremes') { // Prevent feedback loop
                if (thisChart.options.chart.renderTo.indexOf('__mobile_') === -1) {
                    Highcharts.each(Highcharts.charts, function (chart) {
                        if (chart !== thisChart && chart !== undefined && chart.legend !== undefined && chart.options.xAxis[0].type === 'datetime' && chart.options.chart.renderTo.indexOf('__mobile_') === -1) {
                            if (chart.tooltip !== undefined) {
                                chart.tooltip.hide()
                            }
                            if (chart.xAxis[0].cross !== undefined) {
                                chart.xAxis[0].cross.hide()
                            }
                            if (chart.xAxis[0].setExtremes) { // It is null while updating
                                chart.xAxis[0].setExtremes(e.min, e.max, undefined, false, { trigger: 'syncExtremes' });
                            }
                        }
                    });
                }
	        }
	    }

	    /**
	     * In order to synchronize tooltips and crosshairs, override the
	     * built-in events with handlers defined on the parent element.
	     */

	    function showAllCrosshairs(event, container) {
            var chart,
                points,
                i;
            var ev = container.chart.pointer.normalize(event);
            var point = container.chart.series[0].searchPoint(ev, true);
            var x = point.category;

            for (i = 0; i < Highcharts.charts.length; i++) {
                chart = Highcharts.charts[i];
                if (chart !== undefined && chart.pointer !== undefined && chart.options.xAxis[0] && chart.options.xAxis[0].type === 'datetime') {
                    var e = chart.pointer.normalize(event); // Find coordinates within the chart
                    points = [];
                    for (var j = 0; j < chart.series.length; j++) {
                        if (chart.series[j].visible && chart.series[j].type !== 'flags') {
                            var pp = chart.series[j].points.filter(function (p) {
                                    return p.category === x;
                                }
                            );
                            if (pp[0] !== undefined) {
                                points.push(pp[0]);
                            }
                        }
                    }
                    if (points.length) {
                        chart.tooltip.refresh(points); // Show the tooltip
                        chart.xAxis[0].drawCrosshair(e, points[0]); // Show the crosshair
                    }
                }
            }
        }

        function hideAllCrosshairs(event) {
            for (var i = 0; i < Highcharts.charts.length; i++) {
                var chart = Highcharts.charts[i];
                if (chart !== undefined && chart.options.xAxis[0] && chart.options.xAxis[0].type === 'datetime') {
                    chart.options.chart.enabledTracking = true;
                    if (chart.tooltip !== undefined) {
                        chart.tooltip.hide()
                    }
                    if (chart.xAxis[0].cross !== undefined) {
                        chart.xAxis[0].cross.hide()
                    }
                }
            }
        }
	} // end of _draw func

	function _getDefaultConfig() {
		return {
			chart : {
				animation : false,
				marginRight : 5,
				marginLeft : 5,
				alignTicks : false,
				zoomType : 'x',
				height: 400,
				reflow: true,
				style: {
	                fontFamily: 'Yandex Sans Text Web'
	            }
			},
			plotOptions : {
				area : {
					lineWidth : 0,
					fillOpacity : 1,
				},
				line : {
					lineWidth : 2,
					zIndex : 1,
					shadow : false
				},
				column : {
				},
				spline : {
					zIndex : 1,
				},
				areaspline : {
					lineWidth : 0,
					fillOpacity : 1,
				},
				series : {
					marker : {
						enabled : false,
						states : {
							hover : {
								enabled : false
							}
						}
					},
					animation : false,
					connectNulls: true,
					turboThreshold : 5000,
					cropThreshold : null,
	                states: {
	                    hover: {
	                        enabled: false
	                    }
	                },
				},
			},
			credits : {
				enabled : false,
			},
			navigator: {
	            enabled: false,
	        },
	        navigation: {
	            buttonOptions: {
	                enabled: false,
	            }
	        },
	        rangeSelector: {
	        	enabled: false,
	        },
	        scrollbar: {
	        	enabled: false,
	        },
	        exporting: {
	            type: 'image/png',
	        },
			title: {
				style: {
					color: '#2a52be',
	   				fontFamily: '"Yandex Sans Text Web","Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif;',
	   			},
			},
			tooltip : {
				hideDelay: 0,
				animation : true,
				shared : true,
				borderRadius : 4,
				borderWidth : 1,
				borderColor: '#999',
	            shadow: false,
				xDateFormat : '%H:%M:%S',
				crosshairs : {
					width : 1,
					color : '#BBB',
					zIndex: 100
				},
				style: {
           			fontSize: '15px',
           			fontFamily: '"Yandex Sans Text Web", Arial, Helvetica, sans-serif',
	            },
	            useHTML: true,
			},
			legend : {
				//maxHeight: 42,
				enabled: true,
				itemMarginBottom: 5,
				align : 'center',
				verticalAlign : 'bottom',
				itemStyle: {
	                color: '#333',
	                fontWeight: 'bold',
	            },
				borderWidth : 0
			},
			series : []
		};
    }
})();

