soundManager.debugMode = false; // disable debug mode
soundManager.flashVersion = 9;
soundManager.url = '/js/sound/swf/';
soundManager.useHighPerformance = true;
soundManager.useConsole = false;
soundManager.defaultOptions.multiShot = true;
soundManager.onload = function(){
	var sound = soundManager.createSound({
		id: 'twttr',
		url: '/js/audio/logout.mp3'
	});
};


$(document).ready(function(){

	
	var askonexit = true;
	var title_blinker = false;
	var hasFocus = true;
	
	$('#log').attr({'action':'/chat/save_log/'});
	
	function blinkTitle(){
		if(title_blinker){
			return;
		}
		title_blinker = setInterval(function(){
			if(document.title.indexOf('*') != -1){
				document.title = document.title.replace(/\*/g, '=');
			}else if(document.title.indexOf('=') != -1){
				document.title = document.title.replace(/\=/g, '*');
			} else{
				document.title = '*** '+document.title+' ***';
			}
		}, 1000);
	}
	function unblinkTitle(){
		document.title = document.title.replace(/\=/g, '');
		document.title = document.title.replace(/\*/g, '');
		clearInterval(title_blinker);
		title_blinker = false;
	}
	
	function escape_html(html){
		return html.replace(/&/gmi, '&amp;').replace(/"/gmi, '&quot;').replace(/>/gmi, '&gt;').replace(/</gmi, '&lt;')
	}
	
	$('#sound_change_link').click(function(){
		if($('#sound_state').text() == 'Звук включен'){
			//выключаем
			soundManager.getSoundById('twttr').mute();
			$('#sound_img').attr({'src':'/site_media/img/sound_mute.png'});
			$('#sound_change_link').text('Включить звук');
			$('#sound_state').text('Звук выключен');
		}else{
			//включаем
			soundManager.getSoundById('twttr').unmute();
			$('#sound_img').attr({'src':'/site_media/img/sound.png'});
			$('#sound_state').text('Включить звук');
			$('#sound_change_link').text('Выключить звук');
			$('#sound_state').text('Звук включен');
		}
		return false;
	});
	
	function onWindowBlur(){
		hasFocus = false;
	}
	function onWindowFocus(){
		hasFocus = true;
		unblinkTitle();
	}
	
	var isIE = (navigator.appName == "Microsoft Internet Explorer");
	if(isIE){	
		document.onfocusout = function() { onWindowBlur(); };
		document.onfocusin = function() { onWindowFocus(); };
	}else{
		window.onblur = function () {onWindowBlur();};
		window.onfocus = function () {onWindowFocus();};
	}
	
	function randomUUID() {
		var s = [];
		var itoh = new String('0123456789ABCDEF');
		var i;
		for (i = 0; i < 36; i++) {
			s.push(Math.floor(Math.random() * 0x10));
		}
		s[14] = 4;  // Set 4 high bits of time_high field to version
		s[19] = (s[19] & 0x3) | 0x8;
		for (i = 0; i <36; i++){
			s[i] = itoh.charAt(s[i]);
		}
		s[8] = s[13] = s[18] = s[23] = '-';
		return s.join('');
	}
	
	function log(){
		if (window.console) {
			console.log(arguments);
		}
	}
	
	$('#text').keypress(function(e){
		if (e.which == 13){
			return false;
		}else{
			return true;
		}
	});
	
	/*
	 * Pinger
	 */
	
    var Pinger = function(){
        if (!(this instanceof Pinger)){
            throw new Error('use `new`, Luke!');
        }
		var self = this;
        var ping_counter = 0;
		var zeroping = 0;
		var sendPing = null;
		var check_disconnect = null;
		//
		var partner_uid = null;
        
        this.receivePing = function(){
            ping_counter++;
        };
        
		this.init = function(p_uid){
			partner_uid = p_uid;
			
	        check_disconnect = setInterval(function() {
	            log('ping_counter>>', ping_counter);
	            if(ping_counter === 0){
					zeroping++;
	            }else{
					zeroping = 0;
				}
				if (zeroping == 6){
					self.getCmp('fsm').enterState('disconnected', ['network']);
				}
	            ping_counter = 0;
	        }, 10000);
			
	        sendPing = setInterval(function() {
	            self.getCmp('stomp').send('***ping***', '/topic/'+partner_uid);
	        }, 2000);
			
		};
		
		
		this.clearPing = function(){
			clearInterval(sendPing);
			clearInterval(check_disconnect);
			ping_counter = 0;
		};
    };
    
	/*
	 * Typer
	 */
    var Typer = function(){
        if (!(this instanceof Typer)){
            throw new Error('use `new`, Luke!');
        }
		var typing_flag = false;
		var last_typed_time = new Date();
		var self = this;
		var check_stoptyping = null;
		
		var partner_uid = null;
		
		this.receiveTyping = function(){
			$('#partner_typing').html('Собеседник печатает...');
		};
		
		this.receiveStopTyping = function(){
			$('#partner_typing').html('');
		};
		
		this.keyPress = function(e){
	        if (e.which == 13){
				//$('#text').val($('#text').val().slice(0,-1));
                typing_flag = false;
                this.getCmp('chatter').sendMessage();
            }else{
                if (!typing_flag){
                    typing_flag = true;
					if (!partner_uid){
						log('warning! typer is not initialized');
					}
					this.getCmp('stomp').send('***typing***', '/topic/'+partner_uid);
                }
                last_typed_time = new Date();
            }
		};
		
		this.init = function(p_uid){
			partner_uid = p_uid;
	        check_stoptyping = setInterval(function(){
	            if (typing_flag){
	                var diff = new Date() - last_typed_time;
	                if (diff > 3000){
	                    typing_flag = false;
	                    self.getCmp('stomp').send('***stop_typing***', '/topic/'+partner_uid);
	                }
	            }
	        }, 500);
		};
		
    };
	
	/*
	 *
	 */
	
	var StatusHandler = function(){
		if (!(this instanceof StatusHandler)){ throw new Error('!!!');}
		var self = this;
		
		this.init = function(partner_uid){
			$('#status_select option').attr({'selected':''});
			$('#status_select option.status_online').attr({'selected':'selected'});
			$('#status_select').change(function(){
				var curstatus = $('#status_select option:selected').attr('name');
				$('#status_select').removeClass('status_online').removeClass('status_comeback').addClass('status_'+curstatus);
				self.getCmp('stomp').send('***status_'+curstatus+'***', '/topic/'+partner_uid);
			});
		};
		
		this.receiveStatus = function(frame){
			var msg;
			if (frame.body == '***status_online***'){
				msg = 'Некто вернулся';
			}else{
				msg = 'Некто отошёл, но сказал, что вернётся быстро';
			}
			$('#messages').append('<div class="msg_from"><span class="status_msg">'+msg+'<\/span><\/div>');
		};
	};
	
	/*
	 * Chatter
	 */
    
    var Chatter = function(){
        if (!(this instanceof Chatter)){
            throw new Error('use `new`, Luke!');
        }
		var partner_uid = null;
		
		this.receiveMessage = function(frame){
            $('#messages').append('<div class="msg_from"><span class="name">Некто:</span>'+escape_html(frame.body+'')+'<\/div>');
            $('#messages').scrollTop(100000000);
			this.getCmp('typer').receiveStopTyping();
			if(!hasFocus){
				blinkTitle();
			}
		};
		
		this.sendMessage = function(){
			//var message = $('#text').val().replace(/<\/?[^>]+>/gi, '');
			var message = $('#text').val();
			log(message);
			if (!partner_uid){
				log('warning! chatter was not initialized');
			}
            this.getCmp('stomp').send(message, '/topic/'+partner_uid);
            $('#messages').append('<div class="msg_to"><span class="name">Я:</span>'+escape_html(message)+"<\/div>");
            $('#messages').scrollTop(100000000);
			$('#text').val("a").val('');
			$('#text').focus();
			
		};
		
		this.init = function(p_uid){
			partner_uid = p_uid;
		};
    };
    
	/*
	 * Stomp
	 */
    
	var Stomp = function(){
		var stomp = new STOMPClient();
		var self = this;
		var my_uid = null;
        stomp.onopen = function(){};
        stomp.onclose = function(c){
            log('close!! ');
        };
        stomp.onerror = function(error) {alert("Error: " + error);};
        stomp.onerrorframe = function(frame) {alert("Error: " + frame.body);};
        stomp.onconnectedframe = function() {
			if (!my_uid){
				log('error in stomp!');
			}
            stomp.subscribe('/topic/'+my_uid);
        };
        stomp.onmessageframe = function(frame) {
            switch(frame.body){
                case '***typing***':
                    self.getCmp('typer').receiveTyping();
                    break;
                case '***stop_typing***':
                    self.getCmp('typer').receiveStopTyping();
                    break;
                case '***ping***':
                    self.getCmp('pinger').receivePing();
                    break;
                case '***disconnect***':
                    self.getCmp('fsm').enterState('disconnected', ['patner disconnected']);
                    break;
				case '***status_online***':
				case '***status_comeback***':
					self.getCmp('statushandler').receiveStatus(frame);
					break;
                default:
					log('received message', frame);
					soundManager.play('twttr');
                    self.getCmp('chatter').receiveMessage(frame);
                    break;
            }
        };
		this.send = function(){
			stomp.send.apply(stomp, arguments);
		};
		this.disconnect = function(){
			stomp.disconnect.apply(stomp, arguments);
		};
		this.init = function(m_uid){
			my_uid = m_uid;
	        stomp.connect('localhost', 61613, 'guest', 'guest');
		};
	};
	
    var StateMachine = function(){
        this.states = ['offline', 'waiting', 'chat', 'disconnected'];
        this.current = 'offline';
        if (!(this instanceof StateMachine)){
            throw new Error('use `new`, Luke!');
        }
        this.conversions = [
            [['offline', 'waiting'], 'doWait'],
            [['waiting', 'chat'], 'doChat'],
            [['chat', 'disconnected'], 'doDisconnect'],
            [['disconnected', 'waiting'], 'doWaitFromDisconnect']
        ];
		
		this.components = [
			['stomp',new Stomp()],
			['pinger',new Pinger()],
			['typer',new Typer()],
			['statushandler', new StatusHandler()],
			['chatter',new Chatter()],
			['fsm',this]
		];
		var self = this;
		for (var i=0; i<this.components.length; i++){
			//alert(components[i]);
			this.components[i][1].getCmp = function(name){
				for (var j=0; j<self.components.length; j++){
					if (self.components[j][0] == name){
						return self.components[j][1];
					}
				}
				return null;
			};
		}
        
        this.enterState = function(to_state, params){
            var pair = [this.current, to_state];
            var found = false;
            for (var i=0; i< this.conversions.length; i++){
                if (this.conversions[i][0][0] == pair[0] && this.conversions[i][0][1] == pair[1]){
                    found = this.conversions[i];
                    break;
                }
            }
            if (found === false){
                throw new Error('Wrong conversion!');
            }else{
                this.current = found[0][1];
                this[found[1]].apply(this, params || []);
            }
        };
        
        this.doWait = function(){
			$('#disconnect_btn').attr({'disabled':'disabled'});
			$('#status_select').attr({'disabled':'disabled'})
			$('#progressbar').show();
			askonexit = true;
			//$('#partner_typing').html('Выбираем собеседника');
            log('waiting...');
            var uid = randomUUID();
            log('uid>>'+uid);
			var self = this;
			this.getCmp('stomp').init(uid);
            $.getJSON('/chat/add_to_queue/'+uid+'/?jsoncallback=?', function(res){
                var interval = null;
                var counter = 0;
                (function do_that(){
                    counter++;
                    log('waiting counter>>',counter);
                    $.getJSON('/chat/get_partner/'+uid+'/?jsoncallback=?', function(data){
                        log('get partner data>>',data);
                        if (data.partner == 'wait'){
                            interval = setTimeout(do_that, 1000);
                        }else{
							setTimeout(function(){
								$('#partner_typing').empty();
	                            self.enterState('chat',[uid,data.partner, data.online]);
							}, 2000);
                        }
                    });
                })();
            });//eo $.getJSON
        };//eo doWait
        
        this.doChat = function(my_uid, partner_uid, online_count){
			log('chatting!...');
			var self = this;
			this.getCmp('pinger').init(partner_uid);
			this.getCmp('typer').init(partner_uid);
			this.getCmp('chatter').init(partner_uid);
			this.getCmp('statushandler').init(partner_uid);
			var typer = this.getCmp('typer');
			
			$('#progressbar').hide();
			$('#online_count').text(online_count);
			$('#messages').append('<div class="sysmsg">Чат начат. Поприветствуйте собеседника.<\/div>');
	        $('#text').bind('keypress', function(e){
				if($('#text').val() != ""){
					typer.keyPress(e);
				}
			});
			
			$('#disconnect_btn').attr({'disabled':''});
			$('#status_select').attr({'disabled':''})
			
			$('#disconnect_btn').click(function(){
				if (confirm("Вы действительно хотите прервать беседу?")){
					self.getCmp('stomp').send('***disconnect***', '/topic/'+partner_uid);
					$.getJSON('/chat/kill_pair/'+my_uid+'/?jsoncallback=?', function(res){log('killpair get complete');});
					self.enterState('disconnected', ['you disconnected']);
				}
			});
			$('#submit_btn').click(function(){
				if($('#text').val() != ""){
					typer.keyPress({which:13});
				}
			});
        };//eo doChat
        
        this.doDisconnect = function(reason){
			$('#disconnect_btn').attr({'disabled':'disabled'});
			$('#status_select').attr({'disabled':'disabled'})
			askonexit = false;
			this.getCmp('pinger').clearPing();
			this.getCmp('stomp').disconnect('/topic/'+this.getCmp('partner_uid'));
			var log = $('#messages').html();
			$('#messages').append('<div class="disconnected">Беседа прервана. Начать <span id="retalk">новую беседу<\/span> или <span id="save_log">сохранить лог<\/span><\/div>');
			$('#messages').scrollTop(100000000);
			$('#retalk').bind('click', function(){
				askonexit = false;
				if(document.location.href.indexOf('retalk') != '-1'){
					location.href=location.href;
				}else{
					location.href=location.href+'?retalk';
				}
			});
			$('#save_log').bind('click', function(){
				askonexit = false;
				$('#log_html').attr({value:log});
				//console.log(divs);
				/*jQuery.each(divs, function(div){
					console.log($(div).html());
				});
				askonexit = false;
				$('#log').submit();*/
				$('#log').submit();
			});
			if (window.console){
				window.console.log('disconnected because of', reason || 'unknown');
			}
			$('#partner_typing').empty();
        };//doDisconnect
    };
	
	/*
	 * Программа из двух строк -)
	 */
	
	function start_chat(){
		$('#prelog').hide();
		$('#messages').empty();
		$('#postlog').show();
		var sm = new StateMachine();
		sm.enterState('waiting');
		window.onunload = function () {};
		window.onbeforeunload = function () {
			if(askonexit){
				return "Точно хотите уйти?";
			}else{
				return;
			}
		};
	}
	
	$('#start').click(function(){ start_chat(); });
    
	if(document.location.href.indexOf('retalk') != '-1'){
		start_chat();
	}
	
});