define(function(require){
	var $ = require('jquery'),
		monster = require('monster'),
		toastr = require('toastr');

	require([
		'datatables.net',
		'datatables.net-bs',
		'datatables.net-buttons',
		'datatables.net-buttons-html5',
		'datatables.net-buttons-bootstrap'
	]);

var app = {
	name: 'callcenter',

	css: [ 'app', 'icons' ],

	i18n: {
		'en-US': { customCss: false },
		'de-DE': { customCss: false },
		'dk-DK': { customCss: false },
		'it-IT': { customCss: false },
		'fr-FR': { customCss: false },
		'nl-NL': { customCss: false },
		'ro-RO': { customCss: false },
		'ru-RU': { customCss: false },
		'pt-PT': { customCss: false },
		'zh-CN': { customCss: false },
		'es-ES': { customCss: false }
	},

	requests: {
		'callcenter.queue.eavesdrop': {
			'verb': 'PUT',
			'url': 'accounts/{accountId}/queues/{queueId}/eavesdrop'
		},
		'callcenter.call.eavesdrop': {
			'verb': 'PUT',
			'url': 'accounts/{accountId}/queues/eavesdrop'
		},
		'callcenter.queues.list': {
			'verb': 'GET',
			'url': 'accounts/{accountId}/queues'
		},
		'callcenter.queues.create': {
			'verb': 'PUT',
			'url': 'accounts/{accountId}/queues'
		},
		'callcenter.queues.get': {
			'verb': 'GET',
			'url': 'accounts/{accountId}/queues/{queuesId}'
		},
		'callcenter.queues.update': {
			'verb': 'POST',
			'url': 'accounts/{accountId}/queues/{queuesId}'
		},
		'callcenter.queues.delete': {
			'verb': 'DELETE',
			'url': 'accounts/{accountId}/queues/{queuesId}'
		},
		'callcenter.queues.stats': {
			'verb': 'GET',
			'url': 'accounts/{accountId}/queues/stats'
		},
		'callcenter.agents.stats': {
			'verb': 'GET',
			'url': 'accounts/{accountId}/agents/stats'
		},
		'callcenter.agents.status': {
			'verb': 'GET',
			'url': 'accounts/{accountId}/agents/status'
		},
		'callcenter.agents.toggle': {
			'verb': 'POST',
			'url': 'accounts/{accountId}/agents/{agentId}/status'
		},
		'callcenter.agents.list': {
			'verb': 'GET',
			'url': 'accounts/{accountId}/agents'
		},
		'callcenter.agents.update': {
			'verb': 'POST',
			'url': 'accounts/{accountId}/queues/{queuesId}/roster'
		}
	},

	load: function(callback){
		var self = this;

		self.initApp(function() {
			callback && callback(self);
		});
	},

	global_timer: false,
	hide_logout: false,
	map_timers: {
		calls_waiting: {},
		calls_in_progress: {}
	},

	vars: {
		users: []
	},

	initApp: function(callback) {
		var self = this;

		monster.pub('auth.initApp', {
			app: self,
			callback: callback
		});

		self.initHandlebarsHelpers();
	},

	initHandlebarsHelpers: function() {
		Handlebars.registerHelper('inc', function(value, options) {
			return parseInt(value) + 1;
		});

		Handlebars.registerHelper('compare', function (lvalue, operator, rvalue, options) {
			var operators, result;

			if (arguments.length < 3) {
				throw new Error('Handlerbars Helper \'compare\' needs 2 parameters');
			}

			if (options === undefined) {
				options = rvalue;
				rvalue = operator;
				operator = '===';
			}

			operators = {
				'==': function (l, r) { return l == r; },
				'===': function (l, r) { return l === r; },
				'!=': function (l, r) { return l != r; },
				'!==': function (l, r) { return l !== r; },
				'<': function (l, r) { return l < r; },
				'>': function (l, r) { return l > r; },
				'<=': function (l, r) { return l <= r; },
				'>=': function (l, r) { return l >= r; },
				'typeof': function (l, r) { return typeof l == r; }
			};

			if (!operators[operator]) {
				throw new Error('Handlerbars Helper \'compare\' doesn\'t know the operator ' + operator);
			}

			result = operators[operator](lvalue, rvalue);

			if (result) {
				return options.fn(this);
			} else {
				return options.inverse(this);
			}

		});
	},

	initHeaderSubmenu: function() {
		var $headerMenu = $('#cc-header-menu');
		$headerMenu.on('mouseenter', function(){
			$(this).find('.js-header-menu-items').show();
			$(this).find('.js-header-menu-title').hide();
		}).on('mouseleave', function(){
			$(this).find('.js-header-menu-items').hide();
			$(this).find('.js-header-menu-title').show();
		}).on('click', function(e){
			e.preventDefault();
		});
	},

	queue_eavesdrop: function (callback) {
		var self = this;

		monster.request({
			resource: 'callcenter.queue.eavesdrop',
			data: {
				accountId: self.accountId,
				generateError: false
			},
			success: function (queue_eavesdrop) {
				callback(queue_eavesdrop.data);
			}
		});
	},

	showEavesdropPopup: function(mode, data) {
		var self = this;

		self.callApi({
			resource: 'device.list',
			data: {
				accountId: self.accountId,
				generateError: false
			},
			success: function (devices) {
				var popup_html = $(monster.template(self, 'eavesdrop_popup', {
					devices: devices.data
				}));

				var i18n = self.i18n.active();

				$('#ring', popup_html).click(function(e) {
					e.preventDefault();

					var requestData = {
						accountId: self.accountId,
						generateError: false,
						data: {
							id: $('#object-selector', popup_html).val()
						}
					};

					if(mode === 'call') {
						requestData.data.call_id = data.call_id;
					} else if(mode === 'queue') {
						requestData.queueId = data.queue_id;
					}

					monster.request({
						resource: 'callcenter.' + mode + '.eavesdrop',
						data: requestData,
						success: function (devices) {
							popup.dialog('close');
						},
						error: function() {
							// monster.ui.alert('Eavesdrop failed');
							console.log(i18n.callcenter.eavesdrop_request_failed);
						}
					});
				});

				$('#cancel', popup_html).click(function(e) {
					e.preventDefault();
					popup.dialog('close');
				});

				var popup = monster.ui.dialog(popup_html, {
					title: i18n.callcenter.select_the_device,
					width: '450px'
				});
			}
		});
	},

/*	listDevices: function (callback) {
		var self = this;

		self.callApi({
			resource: 'device.list',
			data: {
				accountId: self.accountId
			},
			success: function (devices) {
				callback(devices.data);
			}
		});
	},*/

	poll_agents: function (global_data, _container) {
		console.log('Poll agents. Data:');
		console.log(global_data);
		var self = this,
			container = _container,
			polling_interval = 6,
			map_agents = {},
			cpt = 0,
			current_queue,
			current_global_data = global_data,
			stop_light_polling = false,
			poll = function () {
				var data_template = $.extend(true, {}, {
					agents: current_global_data.agents,
					queues: current_global_data.queues
				}); //copy without reference;
				if (stop_light_polling === false) {
					monster.parallel({
							queues_stats: function (callback) {
								self.get_queues_stats(function (data) {
									callback(null, data);
								});
							},
							agents_stats: function (callback) {
								self.get_agents_stats(function (data) {
									callback(null, data);
								});
							},
							agents_status: function (callback) {
								self.get_agents_status(function (data) {
										callback(null, data);
									},
									function (data) {
										callback(null, {});
									}
								);
							}
						},
						function (err, results) {
							console.log('Poll agents. Results:');
							console.log(results);
							data_template = self.format_live_data(data_template, {
								agents_stats: results.agents_stats,
								queues_stats: results.queues_stats,
								agents_status: results.agents_status
							});
							self.dashboardUpdateAllData(null, data_template, self.vars.queue_id);
						}
					);
				}
			},
			huge_poll = function () {
				console.log('huge_poll');
				if ($('#dashboard-content').size() === 0) {
					self.clean_timers();
				} else {
					if (++cpt % 30 === 0) {
						self.fetch_all_data(function (data) {
							self.dashboardUpdateAllData(null, data, self.vars.queue_id);
							current_global_data = data;
						});
					} else {
						poll();
					}
				}
			};

		$.each(global_data.agents, function (k, v) {
			map_agents[v.id] = 'logged_out';
		});

		self.global_timer = setInterval(huge_poll, polling_interval * 1000);
	},

	get_queues_stats: function (callback) {
		var self = this;

		monster.request({
			resource: 'callcenter.queues.stats',
			data: {
				accountId: self.accountId,
				generateError: false
			},
			success: function (data) {
				callback(data.data);
			}
		});
	},

	get_agents_status: function (callback) {
		var self = this;

		monster.request({
			resource: 'callcenter.agents.status',
			data: {
				accountId: self.accountId,
				generateError: false
			},
			success: function (data) {
				console.log('Agents status response:');
				console.log(data);
				callback(data.data);
			}
		});
	},

	get_agents_stats: function (callback) {
		var self = this;

		monster.request({
			resource: 'callcenter.agents.stats',
			data: {
				accountId: self.accountId,
				generateError: false
			},
			success: function (data) {
				console.log('Agents stats response:');
				console.log(data);
				callback(data.data);
			}
		});
	},

	/*get_queues_stats: function (callback) {
		var self = this;

		monster.request({
			resource: 'callcenter.queues.stats',
			data: {
				accountId: self.accountId
			},
			success: function (queues_stats) {
				callback(queues_stats.data);
			}
		});
	},*/

	get_queues: function (callback) {
		var self = this;

		monster.request({
			resource: 'callcenter.queues.list',
			data: {
				accountId: self.accountId,
				generateError: false
			},
			success: function (data) {
				callback && callback(data.data);
			}
		});
	},

	get_agents: function (callback) {
		var self = this;

		monster.request({
			resource: 'callcenter.agents.list',
			data: {
				accountId: self.accountId,
				generateError: false
			},
			success: function (agents) {
				callback(agents.data);
			}
		});
	},

	/*render_callwaiting_list: function (_container) {
		var self = this,
			container = _container || $('#dashboard-content');

		$('#callwaiting-list', container).empty().listpanel({
			label: 'Call Waiting',
			identifier: 'callwaiting-listview',
			data: []
		});
		$('.add_flow', container).empty().html('call_waiting_log');
	},*/

	get_time_seconds: function (seconds) {
		seconds = Math.floor(seconds);
		var hours = Math.floor(seconds / 3600),
			minutes = Math.floor(seconds / 60) % 60,
			remaining_seconds = seconds % 60,
			display_time = (hours < 10 ? '0' + hours : '' + hours)
				+ ':' + (minutes < 10 ? '0' + minutes : '' + minutes)
				+ ':' + (remaining_seconds < 10 ? '0' + remaining_seconds : ''
				+ remaining_seconds);

		return seconds >= 0 ? display_time : '00:00:00';
	},


	format_live_data: function (formatted_data, data) {
		var self = this,

			current_agents_by_queue = {};
		formatted_data.current_timestamp = data.queues_stats.current_timestamp;
		formatted_data.calls_waiting = {};
		formatted_data.calls_in_progress = {};
		formatted_data.agent_status = {
			busy: {},
			wrapup: {},
			paused: {}
		};

		//Reinitializing previous data;
		$.each(formatted_data.queues, function (k, queue) {
			queue.abandoned_calls = 0;
			queue.average_hold_time = self.get_time_seconds(0);
			queue.current_calls = 0;
			queue.total_calls = 0;
			queue.total_wait_time = 0;
		});

		if(data.agents_status) {
			$.each(data.agents_status, function(k, agent_status) {
				if(k in formatted_data.agents) {
					if(agent_status.status === 'outbound') {
						agent_status.status = 'busy';
					}

					if(agent_status.status === 'connected') {
						agent_status.status = 'handling';
					}

					var current_status = agent_status.status;

					formatted_data.agents[k].status = current_status;
					formatted_data.agents[k].status_started = agent_status.timestamp;

					if($.inArray(current_status, ['busy', 'wrapup', 'paused']) >= 0) {
						formatted_data.agent_status[current_status][k] = agent_status;

						if(current_status === 'busy') {
							formatted_data.agents[k].call_time = self.get_time_seconds(formatted_data.current_timestamp - agent_status.timestamp)
						}
						else if(current_status === 'paused') {
							if('pause_time' in agent_status) {
								formatted_data.agents[k].call_time = self.get_time_seconds(agent_status.pause_time - (formatted_data.current_timestamp - agent_status.timestamp))
							}
							else {
								formatted_data.agents[k].call_time = self.get_time_seconds(formatted_data.current_timestamp - agent_status.timestamp)
							}
						}
						else {
							formatted_data.agents[k].call_time = self.get_time_seconds(agent_status.wait_time  - (formatted_data.current_timestamp - agent_status.timestamp));
						}
					}
					else if(current_status === 'connecting') {
						formatted_data.agents[k].current_call = { friendly_title: agent_status.caller_id_name || agent_status.caller_id_number || agent_status.call_id };
					}

					if(current_status !== 'logged_out') {
						$.each(formatted_data.agents[k].queues_list, function(queue_id, queue_data) {
							if(!(queue_id in current_agents_by_queue)) {
								current_agents_by_queue[queue_id] = 1;
							}
							else {
								current_agents_by_queue[queue_id]++;
							}
						});
					}
				}
			});
		}

		$.each(current_agents_by_queue, function(queue_id, count) {
			if(queue_id in formatted_data.queues) {
				formatted_data.queues[queue_id].current_agents = count || 0;
			}
		});

		$.each(data.agents_stats, function(k, agent_stats) {
			if(k in formatted_data.agents) {
				formatted_data.agents[k].missed_calls = agent_stats.missed_calls || 0;
				formatted_data.agents[k].total_calls = agent_stats.total_calls || 0;

				if('queues' in agent_stats) {
					$.each(agent_stats.queues, function(queue_id, queue_stat) {
						if(queue_id in formatted_data.agents[k].queues_list) {
							formatted_data.agents[k].queues_list[queue_id] = {
								id: queue_id || '',
								missed_calls: queue_stat.missed_calls || 0,
								total_calls: queue_stat.total_calls || 0
							};
						}
					});
				}
			}
		});

		if('stats' in data.queues_stats) {
			$.each(data.queues_stats.stats, function(index, queue_stats) {
				var k = queue_stats.queue_id,
					call_id = queue_stats.call_id;

				if(typeof formatted_data.queues[k] == "object") {
					formatted_data.queues[k].current_calls = formatted_data.queues[k].current_calls || 0;

				if('wait_time' in queue_stats && queue_stats.status !== 'abandoned') {
					formatted_data.queues[k].total_wait_time += queue_stats.wait_time;
				}

				if(queue_stats.status === 'abandoned') {
					formatted_data.queues[k].abandoned_calls++;
					formatted_data.queues[k].total_calls++;
				}
				else if(queue_stats.status === 'waiting') {
					formatted_data.calls_waiting[call_id] = queue_stats;
					formatted_data.calls_waiting[call_id].friendly_duration = self.get_time_seconds(formatted_data.current_timestamp - queue_stats.entered_timestamp);
					formatted_data.calls_waiting[call_id].friendly_title = queue_stats.caller_id_name || queue_stats.caller_id_number || call_id;
					formatted_data.queues[k].current_calls++;
				}
				else if(queue_stats.status === 'handled') {
					formatted_data.calls_in_progress[call_id] = queue_stats;
					formatted_data.agents[queue_stats.agent_id].call_time = self.get_time_seconds(formatted_data.current_timestamp - queue_stats.handled_timestamp);
					formatted_data.agents[queue_stats.agent_id].current_call = queue_stats;
					formatted_data.agents[queue_stats.agent_id].current_call.friendly_title = queue_stats.caller_id_name || queue_stats.caller_id_number || call_id;
					formatted_data.calls_in_progress[call_id].friendly_duration = self.get_time_seconds(formatted_data.current_timestamp - queue_stats.entered_timestamp);
					formatted_data.queues[k].total_calls++;

					formatted_data.queues[k].current_calls++;
				}
				else if(queue_stats.status === 'processed') {
					formatted_data.queues[k].total_calls++;
				}}
			});
		}

		$.each(formatted_data.queues, function(k, v) {
			if(v.total_calls > 0) {
				var completed_calls = v.total_calls - v.abandoned_calls;

				v.average_hold_time = self.get_time_seconds(v.total_wait_time / completed_calls);
			}
		});
		return formatted_data;
	},

	format_data: function(data) {
		console.log('format data');
		var self = this,
			formatted_data = {};
		/* Formatting Queues */
		formatted_data.queues = {};

		$.each(data.queues, function(k, v) {
			formatted_data.queues[v.id] = $.extend(true, {
				current_calls: 0,
				total_calls: 0,
				current_agents: 0,
				max_agents: 0,
				average_hold_time: self.get_time_seconds(0),
				total_wait_time: 0,
				abandoned_calls: 0
			}, v);
		});

		/* Formatting Agents */
		formatted_data.agents = {};

		$.each(data.agents, function(k, v) {
			if(v.queues && v.queues.length > 0) {
				formatted_data.agents[v.id] = $.extend(true, {
					status: 'logged_out',
					missed_calls: 0,
					total_calls: 0,
					queues_list: {}
				}, v);
			}

			$.each(v.queues, function(k, queue_id) {
				if(queue_id in formatted_data.queues) {
					formatted_data.queues[queue_id].max_agents++;
					formatted_data.agents[v.id].queues_list[queue_id] = {
						missed_calls: 0,
						total_calls: 0
					};
				}
			});
		});
		formatted_data = self.format_live_data(formatted_data, data);
		return formatted_data;
	},

	render: function(_container) {
		var self = this,
		container = _container || $('#monster_content');

		// account switching for monster-ui
		self.accountId = monster.apps.auth.accountId;

		self.clean_timers();
		self.dashboardRender(_container);
	},

	dashboardRender: function($container) {
		console.log('Dashboard - Render');
		var self = this;

		self.fetch_all_data(function(data) {
			self.dashboardUpdateAllData($container, data, self.vars.queue_id, function(data){
				self.poll_agents(data, $container);
			});
		});
	},

	dashboardUpdateAllData: function($container, data, queueId, callback) {
		console.log('Dashboard - Update all data');
		console.log('Queue id:');
		console.log(queueId);
		var self = this;
		$container = $container || $('#monster_content');

		var queues_html = $(monster.template(self, 'queues_dashboard', {
			queues: data.queues
		}));

		var agents_html = $(monster.template(self, 'agents_dashboard', {
			agents: data.agents
		}));

		var calls_html = $(monster.template(self, 'calls_dashboard', {
			progress: data.calls_in_progress,
			waits: data.calls_waiting
		}));

		var html = $(monster.template(self, 'dashboard', {}));
		$container.empty().append(html);

		var scroll_value = $('.topbar-right .list_queues_inner', $container).scrollLeft() || 0;
		$container.find('#dashboard-view').empty().append(agents_html);
		$container.find('.topbar-right').empty().append(queues_html);
		$container.find('.topbar-right .list_queues_inner').animate({ scrollLeft: scroll_value }, 0);
		$container.find('#callwaiting-list').append(calls_html);

		// self.render_callwaiting_list(dashboard_html);
		$container.empty().append(html);
		self.bind_live_events($container);
		self.render_timers(data);

		if(typeof(queueId) !== 'undefined') {
			self.detail_stat(queueId, $container);
		}
		self.dashboardBindEvents($container);
		self.initHeaderSubmenu();

		if(typeof(callback) === 'function') {
			callback(data);
		}
	},

	render_timers: function(data) {
		var self = this;

		$.each(self.map_timers, function(type, list_timers) {
			$.each(list_timers, function(k, v) {
				clearInterval(v.timer);
			});
		});

		self.map_timers = {
			waiting: {},
			in_progress: {}
		};

		if(data.calls_waiting) {
			$.each(data.calls_waiting, function(k, v) {
				v.duration = data.current_timestamp - v.entered_timestamp;
				self.start_timer('waiting', {data: v, id: k});
			});
		}

		if(data.calls_in_progress) {
			$.each(data.calls_in_progress, function(k, v) {
				v.duration = data.current_timestamp - v.handled_timestamp;
				self.start_timer('in_progress', {data: v, id: v.agent_id});
			});
		}

		if(data.agent_status) {
			if('busy' in data.agent_status) {
				$.each(data.agent_status.busy, function(agent_id, data_status) {
					data_status.duration = data.current_timestamp - data_status.timestamp;
					self.start_timer('agent_status', {data: data_status, id: agent_id});
				});
			}

			if('wrapup' in data.agent_status) {
				$.each(data.agent_status.wrapup, function(agent_id, data_status) {
					data_status.duration = data_status.wait_time - (data.current_timestamp - data_status.timestamp);
					self.start_timer('agent_status', {data: data_status, id: agent_id}, 'decrement');
				});
			}

			if('paused' in data.agent_status) {
				$.each(data.agent_status.paused, function(agent_id, data_status) {
					if('pause_time' in data_status) {
						data_status.duration = data_status.pause_time - (data.current_timestamp - data_status.timestamp);
						self.start_timer('agent_status', {data: data_status, id: agent_id}, 'decrement');
					}
					else {
						data_status.duration = data.current_timestamp - data_status.timestamp;
						self.start_timer('agent_status', {data: data_status, id: agent_id});
					}
				});
			}
		}
	},

	start_timer: function(type, _data, _timer_type) {
		var self = this,
			$target,
			id = _data.id,
			data = _data.data,
			timer_type = _timer_type || 'increment';

		if(type === 'in_progress' || type === 'agent_status') {
			$target = $('.agent_wrapper#'+id+' .call_time .data_value');
		} else if(type === 'waiting') {
			$target = $('.call-waiting[data-call_id="'+id+'"] .timer');
		}

		if(!self.map_timers[type]) {
			self.map_timers[type] = {};
		}

		self.map_timers[type][id] = data;

		self.map_timers[type][id].timer = setInterval(function(){
			if($target.size() > 0) {
				if(timer_type === 'decrement') {
					var new_duration = --self.map_timers[type][id].duration;
					$target.html(self.get_time_seconds(new_duration > 0 ? new_duration : 0));
				}
				else {
					if(self.map_timers[type]) {
						$target.html(self.get_time_seconds(++self.map_timers[type][id].duration));
					}
				}
			} else {
				if(self.map_timers[type][id]) {
					clearInterval(self.map_timers[type][id].timer);
					delete self.map_timers[type][id];
				}
			}
		}, 1000);
	},

	dashboardBindEvents: function($container) {
		var self = this;

		$container.find('.js-open-cc-settings').on('click', function(e) {
			e.preventDefault();
			self.settingsRender($container, function(){
				// Open first queue
				$('#queues-list li:first-child a').click();
			});
		});
	},

	settingsShowMessage: function(msg, msgType, $container) {
		if(!$container) {
			$container = $('#cc-settings-content');
		}

		var msgTypeClass;

		if(typeof(msgType) === 'undefined') {
			msgType = 'info';
		}

		switch(msgType) {
			case 'warning':
				msgTypeClass = 'msg-warning';
				break;
			case 'success':
				msgTypeClass = 'msg-success';
				break;
			default: // 'info'
				msgTypeClass = 'msg-info';
		}

		var $msg = $('<div class="user-message ' + msgTypeClass + '">' + msg + '</div>')
			.prependTo($container).hide().fadeIn();

		$msg.animate({
				backgroundColor: '#ffffff',
				color: '#000000'
			}, 1000
		);

		window.setTimeout(function(){
			$msg.fadeOut(400, function() {
				$msg.remove();
			})
		}, 4000);
	},

	settingsRender: function($container, callback) {
		var self = this;
		var html = $(monster.template(self, 'settings', {}));
		$container.empty().append(html);
		var $queuesListBox = $container.find('#queues-list-container');

		self.settingsQueuesListRender(null, $queuesListBox, function() {
			monster.ui.tooltips($container, {
				options: {
					placement: 'right',
					container: 'body'
				}
			});

			self.settingsBindEvents($container);

			if(typeof(callback) === 'function') {
				callback();
			}
		});

		self.initHeaderSubmenu();
	},

	settingsBindEvents: function($container) {
		var self = this;

		$container.find('.js-open-cc-dashboard').on('click', function(e) {
			e.preventDefault();
			self.render($container);
		});

		$container.find('.js-cc-create-queue').on('click', function(e) {
			e.preventDefault();
			self.settingsQueueNewInit($container);
		});
	},

	settingsQueueNewInit: function($container) {
		var self = this;
		var $parent = $container.find('#cc-settings-content');

		var $queuesList = $('#queues-list');
		$queuesList.find('.active').each(function(e, i) {
			$(this).removeClass('active');
		});
		$queuesList.find('.js-new-queue-item').remove();
		$queuesList.find('#queues-list').append('<li class="js-new-queue-item active"><a href="#">New Queue</a></li>');

		self.settingsQueueFormRender($parent);
	},

	settingsQueueFormRender: function($container, queueData, callback) {
		var self = this;

		var defaultQueueData = {
			connection_timeout: '0',
			member_timeout: '5',
			agent_wrapup_time: '30',
			record_caller: false,
			moh: {},
			notifications: {},
			max_queue_size: '0'
		};

		queueData = $.extend(true, defaultQueueData, queueData || {});
/*		var data = {
			"data": {
				"name": "test2",
				"record_caller": true,
				"moh": "1880ca1c34f3ed88b4071cda175f525e",
				"strategy": "round_robin",
				"call_recording_url": "",
				"agent_wrapup_time": "30",
				"max_queue_size": "0",
				"connection_timeout": "0",
				"enter_when_empty": false,
				"notifications": {
					"hangup": "",
					"pickup": "",
					"method": "GET"
				},


				"member_timeout": "5",
				"ui_metadata": {
					"ui": "kazoo-ui",
					"version": "3.22-0https://github.com/2600hz/kazoo-ui.gittags/3.22.096a18351d378f041d957acd3c1c94c8e6de462ef2015-10-22_01-32-14120"
				}
			},
			"verb": "PUT"
		};*/

		monster.parallel({
				users: function(callback) {
					self.callApi({
						resource: 'user.list',
						data: {
							accountId: self.accountId,
							generateError: false
						},
						success: function (users) {
							callback(null, users.data);
						}
					});
				},
				media: function(callback) {
					self.callApi({
						resource: 'media.list',
						data: {
							accountId: self.accountId,
							generateError: false
						},
						success: function(media, status) {
							callback(null, media.data);
						}
					});
				}
			},
			function(err, results) {
				if (err) {
					console.log('Error');
					console.log(err);
				} else {
					var i18n = self.i18n.active();
					results.media.unshift(
						{
							id: '',
							name: i18n.callcenter.settings.mediaDefault
						},
						{
							id: 'silence_stream://300000',
							name: i18n.callcenter.settings.mediaSilence
						}
					);

					var html = $(monster.template(self, 'settings_queue_form', {
						data: queueData,
						media_list: results.media
					}));

					self.vars.users = results.users;
					console.log('Users:');
					console.log(results.users);

					$container.empty().append(html);
					self.settingsQueueFormBindEvents($container);
					self.settingsQueueAgentsPanelRender(results.users, queueData.agents, $container);

					if(typeof(callback) === 'function') {
						callback(results);
					}
				}

			});
	},

	settingsQueueAgentsPanelRender: function(usersList, selectedAgentsIdList, $container) {
		var self = this,
			agentsList,
			usersWithoutAgents;

		agentsList = self.settingsQueueAgentsPanelExtractAgentsData(selectedAgentsIdList, usersList);
		usersWithoutAgents = self.settingsQueueAgentsPanelGetUsersWithoutAgents(usersList, agentsList);


		var template = $(monster.template(self, 'settings_queue_agents', {
			agents: agentsList,
			users: usersWithoutAgents
		}));

		var $parent = $container.find('#queue-agents-content');
		$parent.html(template);

		self.settingsQueueAgentsPanelInit($parent, function(){
			self.settingsQueueAgentsPanelBindEvents($parent);
		});
	},

	settingsQueueAgentsPanelExtractAgentsData: function(selectedAgentsIdList, usersList) {
		// fill agents list
		var agentsList = [];

		if(!selectedAgentsIdList) {
			return agentsList;
		}

		for(var a=0, alen= selectedAgentsIdList.length; a<alen; a++) {
			for(var u=0, ulen= usersList.length; u<ulen; u++) {
				if(selectedAgentsIdList[a] === usersList[u].id) {
					console.log('selectedAgentsIdList[a]:');
					console.log(selectedAgentsIdList[a]);

					console.log('usersList[u]:');
					console.log(usersList[u]);
					agentsList.push(usersList[u]);
					break;
				}
			}
		}
		return agentsList;
	},

	settingsQueueAgentsPanelGetUsersWithoutAgents: function(users, agents) {
		var usersWithoutAgents = [];

		// reset user's property "isAgent"
		for(var user=0, userLen=users.length; user<userLen; user++) {
			users[user].isAgent = false;
		}

		// set property "isAgent" to user-agents
		for(var u=0, ulen=users.length; u<ulen; u++) {
			for(var a=0, alen= agents.length; a<alen; a++) {
				if(agents[a].id === users[u].id) {
					users[u].isAgent = true;
					break;
				}
			}
		}

		// collect agents
		for(u=0, ulen=users.length; u<ulen; u++) {
			if(!users[u].isAgent) {
				usersWithoutAgents.push(users[u]);
			}
		}

		return usersWithoutAgents;
	},

	settingsQueueAgentsPanelBindEvents: function($parent) {
		var self = this;
		var handledClass= 'js-handled';

		$parent.find('.js-remove-agent').not('.js-handled').on('click', function(e) {
			e.preventDefault();
			$(this).closest('li').remove();
			self.settingsQueueAgentsPanelUpdateUserTable();
		}).addClass(handledClass);

		$parent.find('.js-add-agent').not('.js-handled').on('click', function(e) {
			e.preventDefault();

			var $userContainer = $(this).closest('tr');
			var userId = $userContainer.data('user-id');
			var $agentsList = $('#queue-agents-list');
			var userName = $userContainer.find('.js-user-name').text();

			if($agentsList.find('[data-user-id="' + userId + '"]').length > 0) {
				// already exist
				return;
			}

			var userItemHTML = ('' +
				'<li data-user-id="{{id}}">' +
					'<span class="item-name">{{name}}</span>' +
					'<a href="#" class="js-remove-agent remove-agent-btn">' +
						'<i class="fa fa-remove"></i>' +
					'</a>' +
				'</li>')
					.replace('{{id}}', userId)
					.replace('{{name}}', userName);

			$agentsList.find('.js-empty-item').remove();
			$agentsList.append(userItemHTML);
			self.settingsQueueAgentsPanelBindEvents($agentsList);
			self.settingsQueueAgentsPanelUpdateUserTable();
		}).addClass(handledClass);
	},

	settingsQueueAgentsPanelUpdateUserTable: function() {
		// find exist agents
		var self = this;
		var agentsIdList = [];
		var $agentsItems = $('#queue-agents-list').find('li');

		$agentsItems.each(function(i, el){
			var userId = $(el).data('user-id');
			if(userId) {
				agentsIdList.push(userId);
			}
		});

		console.log('self.vars.users:');
		console.log(self.vars.users);

		self.settingsQueueAgentsPanelRender(self.vars.users, agentsIdList, $('#queue-agents-wrapper'));
	},

	settingsQueueAgentsPanelInit: function($parent, callback) {
		var table = $parent.find('#queue-users-table').DataTable({
			bStateSave: false,
			lengthMenu: [[10, 25, -1], [10, 25, 'All']],
			order: [[ 1, 'asc' ]],
			autoWidth: false,
			columnDefs: [
				{
					targets: 0,
					width: '4%'
				},
				{
					targets  : 'no-sort',
					orderable: false
				}
			],
			language: {
				search: '',
				searchPlaceholder: 'Search...'
			},
			dom: 'ftplB',
			buttons: [],
			initComplete: function(settings, json) {
				if(typeof(callback) === 'function') {
					callback(settings, json);
				}
			}
		});
	},

	settingsQueueFormBindEvents: function($container) {
		var self = this;

		$container.find('.js-save-queue').on('click', function(e) {
			e.preventDefault();

			var data = self.serializeFormElements($container.find('#queue-form'));
			var queueId = $(this).data('queue-id');

			console.log('Queue form data:');
			console.log(data);

			var agentsIdList = [];
			$('#queue-agents-list').find('li[data-user-id]').each(function(i, el) {
				var userId = $(el).data('user-id');
				if(userId) {
					agentsIdList.push(userId);
				}
			});

			self.settingsQueueSave(queueId, data, function(queueData) {
				console.log('Queue was saved');
				console.log(queueData);
				self.settingsAgentsSave(queueData.id, agentsIdList, function(agentsIdList) {
					console.log('Agents were saved');
					console.log(agentsIdList);
					console.log('Queue saving finished!');
					self.settingsQueueAgentsPanelRender(self.vars.users, agentsIdList, $('#queue-agents-wrapper'));
				});
			});

		});

		$container.find('.js-delete-queue').on('click', function(e) {
			e.preventDefault();
			var queueId = $(this).data('queue-id');

			var i18n = self.i18n.active();
			monster.ui.confirm(i18n.callcenter.settings.deleteQueueConfirmText, function() {
				self.settingsQueueRemove(queueId, function() {
					self.settingsRender($('#monster_content'), function(){
						self.settingsShowMessage(i18n.callcenter.settings.deleteQueueSuccessMessage, 'success')
					});
				});
			});
		});
	},

	settingsQueueRemove: function(queueId, callback) {
		var self = this;

		monster.request({
			resource: 'callcenter.queues.delete',
			data: {
				accountId: self.accountId,
				queuesId: queueId,
				generateError: false
			},
			success: function(data, status) {
				if(typeof(callback) === 'function') {
					callback();
				}
			}
		});
	},

	settingsAgentsSave: function(queueId, agentsIdList, callback) {
		var self = this;

		monster.request({
			resource: 'callcenter.agents.update',
			data: {
				accountId: self.accountId,
				generateError: false,
				queuesId: queueId,
				data: agentsIdList
			},
			success: function(data, status) {
				console.log('Agents were saved.');
				console.log(data.data.agents);

				if(typeof(callback) === 'function') {
					callback(data.data.agents);
				}
			}
		});
	},

	serializeFormElements: function($parent, selector) {
		if(typeof(selector) === 'undefined') {
			selector = '.js-to-serialize[name]';
		}

		var result = {};
		$parent.find(selector).each(function(i, el){
			var $el = $(el);
			var name = $el.attr('name');

			if(el.tagName === 'INPUT') {
				if($el.attr('type') === 'checkbox') {
					result[name] = !!$el.is(':checked');
					return;
				}

				if(!!$el.val()) {
					result[name] = $el.val();
					return;
				}
			}

			if(el.tagName === 'SELECT' && !!$el.find('option:selected').val()) {
				result[name] = $el.find('option:selected').val();
			}
		});

		return result;
	},

	settingsQueueSave: function(queueId, queueData, callback) {
		var self = this;

		/*var data = {
			"data": {
				"connection_timeout": "0",
				"member_timeout": "5",
				"agent_wrapup_time": "30",
				"record_caller": true,
				"moh": "1880ca1c34f3ed88b4071cda175f525e",
				"notifications": {"hangup": "", "pickup": "", "method": "GET"},
				"max_queue_size": "0",
				"name": "test2",
				"strategy": "round_robin",
				"call_recording_url": "",
				"enter_when_empty": false,
				"ui_metadata": {
					"ui": "kazoo-ui",
					"version": "3.22-0https://github.com/2600hz/kazoo-ui.gittags/3.22.096a18351d378f041d957acd3c1c94c8e6de462ef2015-10-22_01-32-14120"
				}
			},
			"verb": "PUT"
		};*/

		if(queueId) {
			// Edit exist queue
			monster.request({
				resource: 'callcenter.queues.update',
				data: {
					accountId: self.accountId,
					generateError: false,
			 		queuesId: queueId,
					data: queueData
				},
				success: function(data, status) {
					console.log(data);

					self.settingsQueuesListRender(queueId, null, function() {
						self.settingsQueueEditFormRender(queueId, function() {
							var i18n = self.i18n.active();
							self.settingsShowMessage(i18n.callcenter.settings.saveQueueSuccessMessage);
							if(typeof(callback) === 'function') {
								callback(data.data);
							}
						});
					});
				}
			});
		} else {
			// Create new queue
			monster.request({
				resource: 'callcenter.queues.create',
				data: {
					accountId: self.accountId,
					generateError: false,
					data: queueData
				},
				success: function(data, status) {
					console.log(data);
					self.settingsQueuesListRender(data.data.id, null, function() {
						self.settingsQueueEditFormRender(data.data.id, function() {
							var i18n = self.i18n.active();
							self.settingsShowMessage(i18n.callcenter.settings.createQueueSuccessMessage);
							if(typeof(callback) === 'function') {
								callback(data.data);
							}
						});
					});
				}
			});
		}
	},

	settingsQueuesListRender: function(activeQueueId, $parent, callback) {
		var self = this;

		if(!activeQueueId || typeof(activeQueueId) === 'undefined') {
			activeQueueId = null;
		}

		if(!$parent) {
			$parent = $('#queues-list-container');
		}

		monster.request({
			resource: 'callcenter.queues.list',
			data: {
				accountId: self.accountId,
				generateError: false
			},
			success: function (data, status) {
				console.log(data);

				var i18n = self.i18n.active();

				var map_crossbar_data = function(data) {
					var new_list = [];

					if(data.length > 0) {
						$.each(data, function(key, val) {
							new_list.push({
								id: val.id,
								title: val.name || i18n.callcenter.settings.queueDefaultName
							});
						});
					}

					new_list.sort(function(a, b) {
						return a.title.toLowerCase() < b.title.toLowerCase() ? -1 : 1;
					});

					return new_list;
				};

				var queuesListHtml = $(monster.template(self, 'settings_queues_list', {
					queues: map_crossbar_data(data.data),
					active_queue_id: activeQueueId
				}));

				$parent.empty().append(queuesListHtml);

				self.settingsQueuesListBind($parent);

				if(typeof(callback) === 'function') {
					callback();
				}
			}
		});
	},

	settingsQueuesListBind: function($container){
		var self = this;

		$container.find('.js-select-queue').on('click', function(e) {
			e.preventDefault();

			var $queuesList = $(this).closest('#queues-list');
			$queuesList.find('.active').removeClass('active');
			$queuesList.find('.js-new-queue-item').remove();

			var queueId = $(this).closest('li').addClass('active').data('id');
			console.log('Edit queue: ' + queueId);

			self.settingsQueueEditFormRender(queueId, function(){});
		})

	},

	settingsQueueEditFormRender: function(queueId, callback) {
		var self = this;

		if(!queueId || typeof(queueId) === 'undefined') {
			console.log('Error while edit queue: queue id is undefined');
			return;
		}

		monster.request({
			resource: 'callcenter.queues.get',
			data: {
				accountId: self.accountId,
				generateError: false,
				queuesId: queueId
			},
			success: function(data, status) {
				console.log(data);

				var $parent = $('#cc-settings-content');
				self.settingsQueueFormRender($parent, data.data, callback);
			}
		});
	},

	fetch_all_data: function(callback) {
		console.log('Fetch all data');
		var self = this;

		monster.parallel({
			queues_stats: function(callback) {
				self.get_queues_stats(function(data) {
					callback(null, data);
				});
			},
			agents_stats: function(callback) {
				self.get_agents_stats(function(data) {
					callback(null, data);
				});
			},
			agents_status: function(callback) {
				self.get_agents_status(function(data) {
						callback(null, data);
					},
					function(data) {
						callback(null, {});
					}
				);
			},
			queues: function(callback) {
				self.get_queues(function(_data_queues) {
					callback(null, _data_queues);
				});
			},
			agents: function(callback) {
				self.get_agents(function(_data_agents) {
					callback(null, _data_agents);
				});
			}
		},
		function(err, results) {
			var _data = {
				queues: results.queues,
				agents: results.agents,
				agents_stats: results.agents_stats,
				queues_stats: results.queues_stats,
				agents_status: results.agents_status
			};

			_data = self.format_data(_data);

			if(typeof callback === 'function') {
				callback(_data);
			}
		});
	},

	bind_live_events: function(container) {
		var self = this;

		// list of queues
		$('.js-queues-list > li', container).on('click', function(e) {
			var $queueEl = $(this);

			self.vars.queue_id = $queueEl.attr('id');

			if($queueEl.hasClass('active')) {
				self.vars.queue_id = undefined;
				$('.agent_wrapper', container).css('display', 'inline-block');
				$('.all_data', container).show();
				$('.queue_data', container).hide();
				$('#callwaiting-list li', container).show();
				$('.icon.edit_queue', container).hide();
				$('.icon.eavesdrop_queue', container).hide();
				$('.list_queues_inner > li', container).removeClass('active');
			} else {
				self.detail_stat(self.vars.queue_id, container);
			}
		});

		$('.js-agent-item .js-eavesdrop', container).on('click', function(e) {
			e.preventDefault();
			e.stopPropagation();

			var data = {
				call_id: $(this).data('call_id')
			};

			self.showEavesdropPopup('call', data);
		});

		$('.js-queues-list .js-edit-queue', container).on('click', function(e) {
			e.preventDefault();
			e.stopPropagation();

			var queueId = $(this).closest('li').attr('id');
			self.settingsRender($('#monster_content'), function(){
				$('#queues-list li').filter('[data-id="' + queueId + '"]').addClass('active');
				self.settingsQueueEditFormRender(queueId, function(){})
			});
		});

		$('.js-queues-list li .js-eavesdrop', container).on('click', function(e) {
			e.preventDefault();
			e.stopPropagation();

			var data = {
				queue_id: $(this).closest('li').attr('id')
			};

			self.showEavesdropPopup('queue', data);
		});

		$('.js-login-to-queue', container).click(function(e) {
			e.preventDefault();

			self.changeAgentInQueueStatus($(this), 'login', function(data) {
				console.log('Agent login to queue');
				console.log(data);
			});
		});

		$('.js-logout-from-queue', container).click(function(e) {
			e.preventDefault();

			self.changeAgentInQueueStatus($(this), 'logout', function(data) {
				console.log('Agent logout from queue');
				console.log(data);
			});
		});
	},

	changeAgentInQueueStatus: function($btn, status, callback) {
		var self = this;

		if(status !== 'login' && status !== 'logout') {
			console.log('Unknown agent status: ' + status);
			return;
		}

		var agentId = $btn.closest('.agent_wrapper').attr('id');
		$btn.parent().find('.preloader').remove();
		$('<span class="preloader"></span>').insertAfter($btn);

		monster.request({
			resource: 'callcenter.agents.toggle',
			data: {
				accountId: self.accountId,
				agentId: agentId,
				generateError: false,
				data: {
					status: status
				}
			},
			success: function (data) {
				console.log(data);
				if(typeof(callback) === 'function') {
					callback(data);
				}
			},
			error: function() {
				if(typeof(callback) === 'function'){
					callback();
				}
			}
		});
	},

	detail_stat: function(queue_id, container) {
		console.log('Detail stat');
		console.log('Queue id:');
		console.log(queue_id);
		var self = this,
			$self_queue = $('#' + queue_id, container);

		self.vars.queue_id = queue_id;

		$('.list_queues_inner > li', container).removeClass('active');
		$self_queue.addClass('active');

		$('#callwaiting-list li', container).each(function(k, v) {
			var $v = $(v);

			if(v.getAttribute('data-queue_id') !== queue_id) {
				$v.hide();
			} else {
				$v.show();
			}
		});

		$('.agent_wrapper', container).each(function(k, v) {
			var $v = $(v);

			if($v.data('queues').indexOf(queue_id) < 0) {
				$v.hide();
			} else {
				if(!self.hide_logout) {
					$v.css('display', 'inline-block');
				}
				$('.all_data', $v).hide();
				$('.queue_stat', $v).hide();
				$('.queue_stat[data-id=' + queue_id + ']', $v).show();
				$('.queue_data', $v).show();
			}
		});
	},

	clean_timers: function() {
		var self = this;

		if(self.global_timer !== false) {
			clearInterval(self.global_timer);
			self.global_timer = false;
		}

		$.each(self.map_timers, function(type, list_timers) {
			$.each(list_timers, function(k, v) {
				clearInterval(v.timer);
			});
		});

		self.map_timers = {};
	},

	activate_queue_stat: function(args) {
		//TODO check render global data
		var self = this,
		container = args.container || $('#monster-content');
		container.empty();
		self.render(container, function() {
			var $self_queue = $('#'+args.id, container);
			self.detail_stat(args.id, container);
		});
	}

	/*activate: function(_container) {
		var self = this,
		container = _container || $('#monster-content');
		container.empty();
		self.current_queue_id = undefined;
		self.hide_logout = false;
		//TODO check render global data
		self.render(container);
	},*/

	};

	return app;
});
