var MessageForm = Class.create({

    initialize: function (obj, params) {
        this.form           = obj;
        this.onPost         = params.onPost || function(){ return true; };
        this.emoticons      = params.emoticons;
        
        this.slide          = $$('.slide')[0];
        this.slide.status   = 1;
        this.userID         = false;
        this.textarea       = $$("." + obj.className + " textarea")[0];
        
        this.createEmoticonsDialog();
        
        this.textarea.observe("keypress", this.checkKeypress.bind(this));
        this.form.observe("submit", this.sendForm.bind(this));
    },

    createEmoticonsDialog: function() {
        var emoticonsHolder = new Element('div').addClassName('emoticons');
        Element.insert( this.textarea, { after: emoticonsHolder } );
        this.emoticons.each( function(pair) {
            emoticonsHolder.insert(new Emoticon(pair.key, pair.value.first(), this.textarea).obj);
        }.bind(this));
    },

    checkKeypress: function (ev) {
        var cKeyCode = ev.keyCode || ev.which;
        if (cKeyCode == Event.KEY_RETURN) {
            this.sendForm(ev);
        }
    },

    sendForm: function (ev) {
        var data = this.form.serialize(true);
        new Ajax.Request( this.form.action, {
            parameters: data,
            onComplete: this.evalResponse.bind(this)
        });
        this.textarea.clear();
        Event.stop(ev);
    },

    evalResponse: function (transport) {
        var data = transport.responseText.evalJSON();
        if (data['status'] == false) {
            data = data['data'];
            if(data['text']) {
                this.form.getElementsBySelector("p")[0].insert({bottom: "<br />" + data['text']});
            }
            for (i in data) {
                $(i).addClassName(data[i]);
            }
        } else {
            this.textarea.removeClassName('invalid');
            this.userID = data['data']['chatboxUserID'];
            if (this.slide.status == 1) {
                Effect.BlindUp(this.slide, {duration: 0.5});
                this.slide.status = 0;
            }
            this.onPost(this.userID);
        }
    },

    logout: function () {
        if (! this.userID) {
            return;
        }
        var url = "/chat/action/logout";
        var params = new Hash();
        params.set('userID', this.userID);
        new Ajax.Request( url, {
            parameters: params,
            asynchronous: false
        });
    }

});

var Emoticon = Class.create({
    
    initialize: function (image, sign, textarea) {
        this.obj        = new Element('img', {src: '/images/emoticons/' + image});
        this.textarea   = textarea;
        this.sign       = sign;

        this.obj.observe('click', this.insertEmoticon.bind(this));
        this.obj.observe('mouseover', this.hover);
    },

    hover: function() {
        this.style.cursor = "pointer";
    },

    insertEmoticon: function() {
        if (document.selection) {
            this.textarea.focus();
            sel = document.selection.createRange();
            sel.text = this.sign;
        } else if (this.textarea.selectionStart || this.textarea.selectionStart == '0') {
             var startPos = this.textarea.selectionStart;
             var endPos = this.textarea.selectionEnd;
             this.textarea.value = this.textarea.value.substring(0, startPos) + this.sign + this.textarea.value.substring(endPos, this.textarea.value.length);
        } else {
            this.textarea.value += this.sign;
        }
    }

});

var NicknamesList = Class.create({

    initialize: function (obj) {
        this.list = obj;
        this.nicknamesTemp = $$(".chatbox-list li");
        this.nicknames = new Hash();
        for(var i = 0; i < this.nicknamesTemp.length; i++) {
            var id = this.nicknamesTemp[i].classNames().toArray().last();
            this.nicknames.set(id, this.nicknamesTemp[i]);
        }
    },

    update: function () {
        var url = "/chat/action/get-nicknames";
        new Ajax.Request( url, {
            asynchronous: true,
            onComplete: this.setNicknames.bind(this)
        });
    },

    setNicknames: function (transport) {
        var data = transport.responseText.evalJSON();
        if (data['status'] == false) {
            return;
        }
        data = data['data'];
        for(var id in data) {
            var chatboxUserID = data[id].chatboxUserID;
            if (this.nicknames.get(chatboxUserID) != undefined && data[id].status == 0) {
                this.nicknames.get(chatboxUserID).remove();
                this.nicknames.unset(chatboxUserID);
            }

            if (this.nicknames.get(chatboxUserID) == undefined && data[id].status == 1) {
                this.nicknames.set(chatboxUserID, new Element('li', {
                                        'class': chatboxUserID
                                    }).update(data[id]['nickname']));
                this.list.insert(this.nicknames.get(chatboxUserID));
            }
        }
    }

});

var Message = Class.create({

    initialize: function(id, obj, params, emoticons) {
        this.id = id;
        this.emoticons = emoticons;
        
        if (obj) {
            this.message = obj;
            this.textHolder = obj.childElements()[1];
        } else {
            this.message = new Element('div', { 'class': 'chatbox-message'});
            this.message.insert( 
                new Element('span', { 
                    'class': 'header'
                }).update("Afzender: " + params.user.nickname + ", " + params.timestamp)
            );
            this.textHolder = new Element('p').update(params.message);
            this.message.insert(
                this.textHolder
            );
        }
        this.insertEmoticons();
    },

    getColor: function() {
        return this.message.classNames().toArray()[1];
    },

    setColor: function(color) {
        this.message.addClassName(color);
    },

    insertEmoticons: function () {
        this.textHolder.innerHTML = this.replaceTekst(this.textHolder.innerHTML);
    },

    replaceTekst: function (tekst) {
        this.emoticons.each( function (pair) {
            pair.value.each( function (item) {
                var reg = new RegExp(RegExp.escape(item), "g");
                tekst = tekst.replace(reg, "<img src='/images/emoticons/" + pair.key + "' alt='emoticon' />");
            });
        });
        return tekst;
    }
        
});

RegExp.escape = function(text) {
  
    if (!arguments.callee.sRE) {
        var specials = [
            '/', '.', '*', '+', '?', '|',
            '(', ')', '[', ']', '{', '}', '\\', '$', '='
        ];
        arguments.callee.sRE = new RegExp(
            '(\\' + specials.join('|\\') + ')', 'g'
        );
    }
    return text.replace(arguments.callee.sRE, '\\$1');

}

var Box = Class.create({

    initialize: function (obj, emoticons) {
        this.scrollbar = new Control.ScrollBar('scrollbar_content','scrollbar_track');
        
        //Initialize sound
        soundManager.url = '/mods/chatbox/javascript/swf/';
        soundManager.debugMode = false;
        soundManager.consoleOnly = false;
        
        soundManager.onload = function() {
            soundManager.createSound({
                id:     'notification',
                url:    '/mods/chatbox/media/sonar.mp3',
                volume: 100
            });
        };

        this.chatboxUserID = null;
        this.box = obj;
        this.emoticons = emoticons;
        this.messagesTemp = $$(".chatbox-message");
        this.messages = new Array();
        for(var i = 0; i < this.messagesTemp.length; i++) {
            var id = this.messagesTemp[i].classNames().toArray().last();
            this.messages[id] = new Message(id, this.messagesTemp[i], null, this.emoticons);
        }
        this.scrollDown();
    },

    getNextColor: function() {
        if (this.messages.length > 0 && this.messages.last().getColor() == "white") {
            return "grey";
        } else {
            return "white";
        }
    },
    
    update: function() {
        var url = "/chat/action/get-messages";
        new Ajax.Request( url, {
            asynchronous: true,
            onComplete: this.setMessages.bind(this)
        });
    },

    setMessages: function(transport) {
        var data = transport.responseText.evalJSON();
        if (data['status'] == false) {
            return;
        }
        
        data = data['data'];
        for(var i in data) {
            if (!this.messages[i]) {
                var color = this.getNextColor();
                this.messages[i] = new Message(i, null, data[i], this.emoticons); 
                this.messages[i].setColor(color);
                this.box.insert(this.messages[i].message);
                this.scrollbar.recalculateLayout();
                this.scrollbar.scrollTo('bottom', false);
                if (this.chatboxUserID != data[i].user.chatboxUserID) {
                    soundManager.play('notification');
                }
            }
        }
    },

    scrollDown: function() {
        this.scrollbar.scrollTo('bottom', false);
    },

    setUserID: function( chatboxUserID ) {
        this.chatboxUserID = chatboxUserID;
    }

});

var Chat = {
    
    initialize: function () {
        Chat.Emoticons      = new Hash();
        Chat.Emoticons.set("Smile.png", new Array(":)", ":-)", "=)"));
        Chat.Emoticons.set("Happy.png", new Array(":D", ":-D"));
        Chat.Emoticons.set("Joking.png", new Array(":P", ":-P"));
        Chat.Emoticons.set("Wink.png", new Array(";)", ";-)"));
        Chat.Emoticons.set("Disappointed.png", new Array(":(", ":-("));
        Chat.Emoticons.set("Angry.png", new Array(":@"));
        Chat.Emoticons.set("Cry.png", new Array(":'-(", ":'("));
        Chat.Emoticons.set("Surprised.png", new Array(":O", ":-O", ":-o", ":o"));
        Chat.Emoticons.set("Confused.png", new Array(":S", ":s", "^o)"));
        Chat.Emoticons.set("Dont Tell.png", new Array(":-$"));
        Chat.Emoticons.set("Thumbs Up.png", new Array("(Y)"));
        
        Chat.NicknamesList  = new NicknamesList( $$(".chatbox-list ul")[0] );
        Chat.Box            = new Box( $("scrollbar_content"), Chat.Emoticons );
        Chat.MessageForm    = new MessageForm( $$(".chatbox-form")[0], {
            onPost: function(chatboxUserID) { 
                Chat.Box.setUserID(chatboxUserID);
                Chat.Box.update();
                Chat.NicknamesList.update();
            },
            emoticons: Chat.Emoticons
        });
        
        new PeriodicalExecuter(Chat.NicknamesList.update.bind(Chat.NicknamesList), 10);
        new PeriodicalExecuter(Chat.Box.update.bind(Chat.Box), 10);
    },

    logout: function () {
        Chat.MessageForm.logout();
    }

}

function setCaptcha() {
    var BASE64_DATA = /^data:.*;base64/i;
    var base64Path = "/captcha.php";
    var img = $$('img[alt=code]')[0];
    
    if (BASE64_DATA.test(img.src)) {
        // pass the data to the PHP routine
        img.src = base64Path + "?" + img.src.slice(5);
    }
}

document.observe("dom:loaded", setCaptcha)
document.observe("dom:loaded", Chat.initialize);
Event.observe(window, "beforeunload", Chat.logout);
