var Handlers = {

    /*
	 * -------------------------------------------------------------
	 * Communicate wth Jabber server via BOSH. CENTER of ALL startup
	 * -------------------------------------------------------------
	 */
    onConnect : function ( status , error_condition )
    {
        Strophe.log(Strophe.LogLevel.DEBUG, 'OnConnect status is '+status);
		switch(status)
        {
            case Strophe.Status.AUTHFAIL:
                Strophe.log('The username & password combination is incorrect');
                break;
            case Strophe.Status.CONNFAIL:
                Strophe.log('Strophe failed to connect.'); //  Attempting to reconnect
				//connect(null, true);
                break;
            case Strophe.Status.DISCONNECTED:
                Strophe.log('Strophe is disconnected.');
                $(document).trigger('disconnected');
                break;
			case Strophe.Status.ATTACHED:
				Strophe.log('Strophe is attached.');
                $(document).trigger('attached');
                break;
			case Strophe.Status.CONNECTED:
                Strophe.log('Strophe is connected.');
                $(document).trigger('connected');
                break;
            case Strophe.Status.ERROR:
                Strophe.log('An error has occured. error condition : ' +error_condition);
                break;
        }
    },

    onConnected : function(){
		connection.addHandler(Handlers.onMessageReceived,null,"message","chat");
        connection.addHandler(Handlers.onGCMessageReceived,null,"message","join-request");
		connection.addHandler(ChatDetect.onTypingMessageReceived,null, "message","typing-start");
		connection.addHandler(ChatDetect.onTypingMessageReceived,null, "message","typing-end");

		Me.initialize();
		sendPresence(null);

		if(!DMC || DMC == undefined)
			DMC = new DOMChat($("#chatFunctions"),$('#chatClone')); //initialize objects for chat
    },

    //ON MY STATUS CHANGED!
    onStatusChanged : function( e, jid, params )
    {
	sendPresence(jid,params.mood,params.lang);
        DMC.setMode(jid,(params.lang == DMC.getInfo(jid).lang),ChatConfig.SEE_TRANSLATIONS_ONLY);
        DMC.setMyLanguage(jid, params.lang);
        DMC.setMyMood(jid, params.mood);
        return true;
    },

    onChatStart : function(jid, sid, start_minimized) {

	if(!DMC.__hasObj(jid))
        {
            var node = Strophe.getNodeFromJid(jid);
            var info = RosterManager.getInfo(node);

            if(!info || info.length < 1) //WHAT! Recieved message from a guy not on the Roster. SPAAAAM!
		return false;

            DMC.newChat(jid,node);
            DMC.addPartnerInfo(jid,info.id,info.name,info.image);
            DMC.setInfo(jid,info.language(),info.mood(),info.image);
            DMC.setMyInfo(jid, Me.name, Me.language, Me.mood, Me.id);

            /*
             * If a message has been sent for the first time, this user will not have its session id
             * If the session id was not set, set it here
             * else, use the session id that was passed
             */
            var icsid = (!sid)?connection.rid:sid;
            DMC.setSessionId(jid,icsid);
            var vid = Handlers._getVideoChatId(jid);
            $(DMC.getChat(jid)).find('.videoChat div').attr('id',vid);
            initializeVideoChat(vid, icsid, Strophe.getNodeFromJid(jid));
        }

        if(Strophe.getDomainFromJid(jid) != ChatConfig.DOMAIN) DMC.hideVideoChatPanel(jid)

        if(start_minimized){
            DMC.showChat(jid,ChatConfig.SEE_TRANSLATIONS_ONLY,true);
            DMC.setStyle('new_message');
            //if(window.console) console.log($.browser.msie,$.browser.version.substr(0,1));
            if($.browser.msie) DMC.getChat(jid).find('.chatRecipient > *[class!=name][class!=commands]').hide().attr('style','') //IE7 hack. When item is opened first time the minimized is broken.
        }
        else{
            //DMC.minimizeAll();
            DMC.showChat(jid,ChatConfig.SEE_TRANSLATIONS_ONLY);
            DMC.maximizeChat(jid,true);
        }

        if(!$.support.objectAll) DMC.minimizeVideoChat(jid) //When IE7 (mode) opens the video flash player already has a height, which causes various problems. This call makes sure it is minimized

        return true;
    },

    onChatEnd : function(event, jid){
        if(Strophe.getDomainFromJid(jid) == ChatConfig.PUBLIC_DOMAIN){
            var room = ChatRooms.getRoom(jid);
            //connection.muc.leaveRoom(Me.jid,room);
            connection.roster.disconnect(room);
            connection.roster.disconnect(jid); //connection.muc.leaveRoom(jid, chat_room);

            RosterManager.remove(jid);
            FriendsBox.removeUser(Strophe.getNodeFromJid(jid));
            FriendsBox.updateOnlineFriendsCount(RosterManager.count());
        }

        if(stopPollingTE) stopPollingTE(DMC.getSessionId(jid));
        //Close video chat
        DMC.closeVideoChat(jid);

        //close the chat object and hide the box
        DMC.hideChat(jid);
        DMC.removeChat(jid);

        return true;
    },

    onMessageSend : function(event, jid, obj){

        try{ChatDetect.closeTimer(jid);}catch(e){} //Sends an end typing message

        var mid = DMC.addMessage(jid, true, obj.msg);
        var attrs = getMessageAttributes(jid);
        attrs.mid = mid;

        if(attrs.src_lang == attrs.target_lang){
            sendMessage(jid, mid, obj.msg);
            return true;
        }

        if(obj.suggestion){
            attrs.relatedid         = obj.relatedid;
            attrs.rootid            = obj.rootid;
            //attrs.suggestion_text   = obj.suggestion;
        }

        if(attrs.target_lang && obj.msg && obj.msg.length > 0) //Send to quick translate only if target_lang is valid.
            QuickTranslate(obj.msg, attrs); //dont send message until the Quicktranslate is receieved

        return true;
    },

    onMessageReceived : function ( msg ) {

    	var msg_dom = $(msg);
        var to 		= msg_dom.attr('to');
        var from 	= msg_dom.attr('from');
        var type 	= msg_dom.attr('type');
        var elems 	= msg_dom.find('body');
        var lang 	= msg_dom.attr('xml:lang');
        var src_lang	= msg_dom.attr('src_lang');
        var tgt_lang	= msg_dom.attr('target_lang');
        var mid 	= msg_dom.attr('id');
	var sid		= msg_dom.attr('sid');

       //If the box is hidden or minimized, update the count
        if(DMC.__hasObj(from))
        {
            if(DMC.isHidden(from)){
                DMC.showChat(from,ChatConfig.SEE_TRANSLATIONS_ONLY,true);
                DMC.setStyle(from,'new_message');
            }
            else if(DMC.isMinimized(from))
            {
                /*if(!new_message_counter[from])
                    new_message_counter[from] = 1;
                else
                    ++new_message_counter[from];

                DMC.setMinimizedCount(from,new_message_counter[from]);*/
                if(!$.support.objectAll) {
                        DMC.minimizeChat(from); //For IE explicitly call minimize
                }
                DMC.setStyle(from,'new_message');
            }
            else
                DMC.showChat(from,ChatConfig.SEE_TRANSLATIONS_ONLY);

            var vid = Handlers._getVideoChatId(from);
            updateChatSessionIdExtInt(vid,sid); //update the session id. The funciton will check if it is different from last time.
        }
        else
            Handlers.onChatStart(from,sid,true)

	if(DMC.getSessionId(from) != sid) DMC.setSessionId(from, sid);

        var bodys = new Object();

        if(type == 'chat' && elems && elems.length > 0)
        {
            for( var c = 0; c < elems.length ; c++){
                var lng = $(elems[c]).attr('xml:lang') || $(elems[c]).attr('lang'); //Opera cannot read 'xml:lang'
                bodys[lng] = $(elems[c]);
            }

            DMC.addMessage(from, false, bodys[src_lang].text(), mid);

            if(src_lang != tgt_lang && bodys[tgt_lang] && bodys[tgt_lang].text())
            {
                var status   = bodys[tgt_lang].attr('status') || '';
                var trans_id = bodys[tgt_lang].attr('trans_id') || '';

                DMC.addMessageTranslation(from, mid, bodys[tgt_lang].text(), status, trans_id);

                if($(DMC.getChat(from)).find('input[name=translationSound]').attr('checked')
                    && !isNaN(parseInt(trans_id))
                    && document[ChatConfig.TEXT_TO_SPEECH_OBJ_ID]){
                    var url = ChatConfig.WAVE_URL + parseInt(trans_id);
                    try{document[ChatConfig.TEXT_TO_SPEECH_OBJ_ID].PlaySoundExtInt(url);}catch(e){}
                }

                if(status > 1)
                    startPollingTE(DMC.getSessionId(from),Me.id);
                else if(!DMC.awaitingTranslations(from))
                    stopPollingTE(DMC.getSessionId(from));

                var tm = msg_dom.find('translation_meta');

                if(status == ChatMessageStatus.HUMAN_TRANSLATED)
                {
                    var abbr    = '<a class="report_link" href="#tlang='+tgt_lang+'&src_lang='+src_lang+'&reporterid='+Me.id+'">'+ChatMessages.report_title+'</a>';
                    var report  = ChatMessages.report_translation;// 'Report this translation as incorrect.';
                    DMC.addReport(from,mid,abbr,report);
                }

            }

            if(ChatConfig.PLAY_SOUND) play_sound();
        }

        return true;
    },

    onSuggestionReceived : function ( Nothing , theArray, chat_window, the_sugg_obj, text_object) {

        //RESET THE SUGGESTION ITEMS
        the_sugg_obj.html("");
        text_object.attr("suggestion", "");
        text_object.attr("relatedid", "0");
        text_object.attr("rootid", "0");

        //This function forces the #chatFunctions to redraw everytime a suggestion changes. Due to IE 7/8 CSS rendering bug
        var IEFix = function(){
            if($.support.objectAll) return;
            $('#chatFunctions').attr( 'style','zoom:1; ');
            $('#chatFunctions').width($('#chatFunctions').width()-1);
            $('#chatFunctions').width($('#chatFunctions').width()+1);
        }

        if(theArray.length < 1 || (typeof theArray[0]) != 'object'){
            the_sugg_obj.hide();
            /*if(!$.support.objectAll) //IE bug - probably hasLayout issues that pushes the window down when a suggestion has come
				$('#chatFunctions').height(chat_window.height());*/
            IEFix();
            return true;
        }

        var new_items = '';
        for(var i=0; i<theArray.length; i++) {
            var suggestion = theArray[i];
            var text = suggestion.text;
            if(!text) continue;
            var ar = text.match(/\#[0-9]+\#/g);
            for(var j in ar)
                text = text.replace(ar[j],'<b>'+ar[j]+'</b>');
            the_sugg_obj.append('<li class="'+i+'"><a href="#" relatedid="'+suggestion.textid+'" rootid="'+suggestion.rootid+'" title="'+ChatMessages.choose_sentence+'">'+text+'</a></li>');
        }

        the_sugg_obj.show();

        /*if(!$.support.objectAll){ //IE bug - probably hasLayout issues that pushes the window down when a suggestion has come
	$('#chatFunctions').height(chat_window.height());
	}*/
        IEFix();

        the_sugg_obj.find("li a").click(function(e) {
            text_object.val($(this).text());
            text_object.attr("suggestion", $(this).text());
            text_object.attr("relatedid", $(this).attr("relatedid"));
            text_object.attr("rootid", $(this).attr("rootid"));
            the_sugg_obj.html("");
            the_sugg_obj.hide();
            text_object.focus();

            /*if(!$.support.objectAll) //IE bug - probably hasLayout issues that pushes the window down when a suggestion has come
		$('#chatFunctions').height(chat_window.height());*/
            IEFix();
            return false;
        });

        the_sugg_obj.find('li a').keypress( function(e){
            var parent 	 = $(this).parent();
            var no = parent.removeClass('sugg').attr('class');

            //UP
            if(e.keyCode == 38)
            {
                if(no > 0)
                    parent.siblings('li.'+ (--no)).addClass('sugg').children().focus();
                else
                    parent.addClass('sugg');
            }
            else if(e.keyCode == 40) //DOWN
            {
                if(no < parent.siblings().length)
                    parent.siblings('li.'+ (++no)).addClass('sugg').children().focus();
                else
                    parent.addClass('sugg');
            }

            if(e.keyCode == 13 || e.keyCode == 32) //ENTER of SPACE
                return true;

            return false;
        });

        return true;
    },

    onTranslationRecieved : function (evt, data) {
        if(data.type == "error" || !data.output || data.output == ''){ //If no translation recieved do a machine translation
            //GoogleApi.translate(data.input, data.src_lang, data.target_lang, data);
            //Handlers.onTranslationFailed(null, data);
            $(document).trigger("translation_failed", [data]);
            return true;
        }

        var translated_message = data.output, status = 1;
        var trans_id = null;

        if(data.relatedid) trans_id = 'QT'+data.relatedid;
        else if(data.lid && data.lid > 0) trans_id = 'CT'+data.lid;

        DMC.addMessageTranslation(data.jid, data.mid, translated_message, status, trans_id);
        sendMessage(data.jid,data.mid, data.input, translated_message, status, trans_id);

        /*if(data.ownerid && data.ownername && data.usage_count)
        DMC.addReport(data.jid, data.mid, 'I',' Translated by <a href="#'+data.ownerid+'">'+data.ownername+'</a>. Used '+data.usage_count+' times');*/

        var abbr    = '<a class="report_link" href="#">R</a>';
        var report  = ChatMessages.report_translation;
        DMC.addReport(data.jid, data.mid,abbr,report);
        return true;
    },

    onCommunityTranslationReceived : function(evt, data){
        if(data.type == "error") return true;

        data.jid = DMC.getJidFromSessionId(data.sid);
        if(!data.jid) return false;

        var status = ChatMessageStatus.HUMAN_TRANSLATED;
        DMC.addMessageTranslation(data.jid, data.mid, data.translation, status, "CT"+data.lid); //This needs to be checked!
        var abbr    = '<a class="report_link" href="#">'+ChatMessages.report_title+'</a>';
        var report  = ChatMessages.report_translation;
        DMC.addReport(data.jid, data.mid,abbr,report);
    },

    onTranslationFailed : function (evt, data) {
        GoogleApi.translate(data.input, data.src_lang, data.target_lang, data);
        return true;
    },

    onGoogleTranslate : function(evt, data) {
        var trans = (data.translation)?data.translation:'';
        var status = ChatMessageStatus.MACHINE_TRANSLATED;
        DMC.addMessageTranslation(data.jid, data.mid, trans, status);
        sendMessage(data.jid, data.mid, data.input,trans, status);
        startPollingTE(DMC.getSessionId(data.jid),Me.id);
    },

    onError : function( dom ){
        try{console.log(dom)}catch(e){}
    return true;
},

_getVideoChatId : function( jid ){
    return 'video_'+Strophe.getNodeFromJid(jid);
}
}

var ChatDetect = {
    timers : {},
    timeout: 1000,

    sendTypingMessage : function(to,start){
        if(start == undefined || start != false) start = true;
        var p = $msg({from: connection.jid, to: to, type:(start)?"typing-start":"typing-end"});
        connection.send(p.tree());
    },

    setTimer : function(jid){
        var key = Strophe.getNodeFromJid(jid);
        if(this.timers[key] != undefined ) clearTimeout(this.timers[key]);
        this.timers[key] = setTimeout(function(){ChatDetect.closeTimer(jid);},this.timeout);
    },

    isTimerSet : function(jid){
        return (this.timers[Strophe.getNodeFromJid(jid)] != undefined)
    },

    endTimer : function(jid){
        var key = Strophe.getNodeFromJid(jid) || jid;
        if(this.timers[key] != undefined ) {
            clearTimeout(this.timers[key]);
            delete this.timers[key];
        }
    },

    closeTimer : function(jid){ //Sends a message before closing the timer
        ChatDetect.sendTypingMessage(jid,false);
        ChatDetect.endTimer(jid);
    },

    onTypingMessageReceived : function(msg){
        //if(window.console) console.log(msg);
        //show typing message
        var jid = $(msg).attr('from');
        var type = $(msg).attr('type');
        if(type == "typing-start")
                DMC.displayTypingMessage(jid,true);
        else if(type == "typing-end")
                DMC.displayTypingMessage(jid,false);
        return true;
    }
}

function getMessageAttributes(jid)
{
    var myinfo	= DMC.getMyInfo(jid);
    var tl		= RosterManager.getLanguage(jid);
    var fid		= Me.id;
    var tid		= RosterManager.getId(jid);
    var sender_sees = (!ChatConfig.SEE_TRANSLATIONS_ONLY)?1:0;
    var topics	= DMC.getTopics(jid);
    var sid		= DMC.getSessionId(jid); //this Session ID identifies a chat session between two users. Both users will use this sid during their conversation

    if(!sid){
        DMC.setSessionId(jid,connection.rid);
        sid = connection.rid;
    }

    var attr = {from: Me.jid, to:jid, fid:fid, tid:tid, sid:sid, sender_sees:sender_sees, type:'chat', src_lang:myinfo.lang, target_lang:tl, mood:myinfo.mood, topics:topics};
    return attr;
}

function sendMessage(jid, mid, message, translated_message, status, translated_message_id)
{
    var reply = '';
    var attr = getMessageAttributes(jid);
    attr.id = mid;

    if(translated_message)
    {
            var att = {"xml:lang" : attr.target_lang, 'status' : status};
            if(translated_message_id) att.trans_id = translated_message_id;

            reply = new Strophe.Builder("message",attr).c('body', {"xml:lang" : attr.src_lang}).t(message)
                                                                                      .up().c('body', att).t(translated_message);
    }
    else
            reply = new Strophe.Builder("message",attr).c('body', {"xml:lang" : attr.src_lang}).t(message);

    connection.send(reply.tree());

    if(Strophe.getDomainFromJid(jid) == ChatConfig.DOMAIN)
        logMessage(jid, attr.sid, attr.src_lang, attr.target_lang, message, translated_message, mid, status);

    return mid;
}

function logMessage(jid, cid, lang_from, lang_to, msg, tmsg, mid, status){
    var url = ChatConfig.CHAT_LOG_URL;
    var info = RosterManager.getInfo(jid);
    var data = {cid:cid,message:msg,tmessage:(!tmsg)?null:tmsg,lfrom:lang_from,lto:lang_to,to_id:info.id,tname:info.name,mid:mid,status:status};

    $.post(url, data, function(json){try{console.log(json);}catch(e){}}, 'json');
}

function sendPresence(to_jid, mood, language, show)
{
    var lang_id	= ChatLanguages.getLanguageId((language)?language:Me.language);
    var lang_name	= ChatLanguages.getLanguageName((language)?language:Me.language);
    var lang_code	= (language)?language:Me.language;

    connection.roster.sendPresence(to_jid, Me.id, Me.name, Me.image, (mood)?mood:Me.mood, lang_code, lang_id, lang_name, show);
}

function disconnect(){
    if(isConnected()){
        if(Handlers.onDisconnected) Handlers.onDisconnected();
        connection.send($pres({"type": "unavailable"}));
        connection.flush();
        connection.disconnect();
        connection.reset();
        $(document).trigger('disconnected');
    }
    return true;
}

function isConnected(){
    return (connection && connection.connected);
}

function bindDefaultHandlers(){
    $(document).bind('connected',           Handlers.onConnected);
    $(document).bind('disconnected',        Handlers.onDisconnected);
    $(document).bind('roster_changed',      Handlers.onRosterChanged);
    $(document).bind('chat_ended',          Handlers.onChatEnd);
    $(document).bind('message_send',        Handlers.onMessageSend);
    $(document).bind('status_changed',      Handlers.onStatusChanged);
    $(document).bind("translation_recieved",Handlers.onTranslationRecieved);
    $(document).bind("translation_failed",  Handlers.onTranslationFailed);
    $(document).bind("machine_translated",  Handlers.onGoogleTranslate);
    $(document).bind("SE_FOUND",            Handlers.onSuggestionReceived);
    $(document).bind("TE_POLL_EVENT",       Handlers.onCommunityTranslationReceived);
}

/*
 * GOOGLE TRANSLATE
 */

function mt_load()
{
    var script = document.createElement("script");
    script.src = "http://www.google.com/jsapi?callback=loadGoogleTranslate";
    script.type = "text/javascript";
    document.getElementsByTagName("head")[0].appendChild(script);
}

function loadGoogleTranslate(){
    try{
        google.load("language", "1",{"callback" : GoogleApi.loaded});
    }catch(e){if(window.console)console.log('loadTranslate failed',e);}
}

var GoogleApi = {

    loaded : function(data){
        $(document).trigger("google_loaded", [data]);
    },

    translate : function(input, src_lng, tgt_lng, data){
        //try{console.log('GoogleApi.translate',input, src_lng, tgt_lng, data)}catch(e){}
        try {
            google.language.translate(input, src_lng, tgt_lng, function (result) {
                data.translation = result.translation;
                try{Logger.log('google.language.translate : [SUCCESS] ','"'+input+'"['+src_lng+']','>','"'+result.translation+'"['+tgt_lng+']');}catch(e){}
                $(document).trigger("machine_translated", [data]);
            });
        }catch(e){mt_load();$(document).trigger("machine_translated", [data]);}
    }
}
