var emoji = (function () {
    var isIE = navigator.userAgent.toUpperCase().indexOf("MSIE") > -1;
    var gf = function ( id ) {
        return ( $(id).contentWindow ) ? $(id).contentWindow : frames[id] ;
    }
    var each = function ( obj, iter ) {
        for ( var i = 0; i < obj.length; i++ ) {
            iter.call( null, obj[i], i);
        }
    }
    var addEventListener = function (obj, name, observer, useCapture) {
        if ( obj.attachEvent ) {
            obj.attachEvent("on" + name, observer);
        } else if(obj.addEventListener) {
            obj.addEventListener(name, observer, useCapture);
        }
    }
    var removeEventListener = function (obj, name, observer, useCapture) {
        if ( obj.removeEvent ) {
           obj.removeEvent("on" + name, observer);
        } else if ( obj.removeEventListener ) {
           obj.removeEventListener(name, observer, useCapture);
        }
    }
    var getXY = function (element) {
        this.element = ( typeof element == 'string' ) ? document.getElementById( element ) : element;
        if ( this.element.getBoundingClientRect ) {
            var box        = this.element.getBoundingClientRect();
            var scrollTop  = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
            var scrollLeft = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
            return {
                top  : box.top  + scrollTop + 3,
                left : box.left + scrollLeft - 2                                                                                             
            }
        } else if ( document.getBoxObjectFor ) {
            var box = document.getBoxObjectFor( this.element );
            return {
                top  : box.y,
                left : box.x
            }
        } else {
            var pos = {
                top  : this.element.offsetTop,
                left : this.element.offsetLeft
            }
            var parent = this.element.offsetParent;
            if ( this.element != parent ) {
                while ( parent ) {
                    pos.top  += parent.offsetTop;
                    pos.left += parent.offsetLeft;
                    parent    = parent.offsetParent;
                }
            }
            return pos;
        }
    }   
    var Class = {
        create : function () {
            return function () {
                this.initialize.apply(this, arguments);
            }
        }
    }
    var Selection = Class.create();
    Selection.prototype = {
        initialize : function ( element ) {
            this.element = element;
            this.pos     = {
                start  : null,
                end    : null,
                before : null,
                after  : null,
                middle : null,
                len    : null
            }
            this.tab     = "\t";
            this.tab_exp = /\t/;
        },
        create : function () {
            if ( document.selection ) {
                this.element.focus();
                {
                    range = document.selection.createRange();
                    range.text = this.tab + range.text + this.tab;
                    while ( this.tab_exp.test( this.element.value ) ) {
                        var key = ( this.pos[ "start" ] == null ) ? "start" : "end";
                        this.pos[ key ]    = this.element.value.indexOf( this.tab );
                        this.element.value = this.element.value.replace( this.tab, "" );
                    }
                }
                {
                    this.pos = {
                        start   : this.pos[ "start" ],
                        end     : this.pos[ "end" ],
                        before  : this.element.value.substring( 0, this.pos[ "start" ] ) || "",
                        after   : this.element.value.substring( this.pos[ "end" ], this.element.value.length ) || "",
                        middle  : this.element.value.substring( this.pos[ "start" ], this.pos[ "end" ] ) || "",
                        len     : this.element.value.length
                    }
                    if ( navigator.userAgent.toUpperCase().indexOf("MSIE") > 0 )
                        this.pos.start += ( this.pos.middle.match(/\x0D\x0A|\x0D|\x0A/g) || [] ).length;
                    return this.pos;
                }
            } else if ( this.element.selectionStart || this.element.selectionStart == '0' ) {
                    {
                    return this.pos = {
                        start   : this.element.selectionStart,
                        end     : this.element.selectionEnd,
                        before  : this.element.value.substring( 0, this.element.selectionStart ) || "",
                        after   : this.element.value.substring( this.element.selectionEnd, this.element.value.length ) || "",
                        middle  : this.element.value.substring( this.element.selectionStart, this.element.selectionEnd ) || "",
                        len     : this.element.length
                    }
                }
            }
        }
    }     
    return {
           init : function ( target, pb, pallet, map_id, wysiwyg) {
                {
                    if ( target instanceof Array) {} else { target = [target] };
                    if ( pb instanceof Array) {} else { pb = [pb] };
                    for ( var i = 0; i < target.length; i++ ) {
                        if ( !document.getElementById( target[i] ) )
                            return false;
                    }
                }
                {
                    this.target  = target;
                    this.wysiwyg = wysiwyg ? gf( wysiwyg ) : null;
                }
                {
                    var close_pallet = function (event) {
                         if ( event.shiftKey ) {
                            if ( isIE )
                               return false;
                            if ( event.target && event.target.tagName == "AREA" )
                               return false;
                         }
                         if ( document.getElementById( pallet ).style.display == "" ) {
                            document.getElementById( pallet ).style.display = "none";
                            removeEventListener( document.body, "mouseup", close_pallet, false);
                         }
                    };
                }
                {
                    function set_pallet (_target, _pb) {
                        return function(event) {
                            var pos  = getXY(_pb);
                            var diff = isIE ? 22 : 28;
                            with ( document.getElementById( pallet ).style ) {
                                display = "";
                                top     = pos.top  + diff  + "px";
                                left    = pos.left + "px"; 
                            }   
                            document.getElementById( 'active_target' ).value = _target;
                            setTimeout( function () {
                                addEventListener( document.body, "mouseup", close_pallet, false);
                            }, 10);
                        }
                   }
                }
                {
                    for ( var i = 0; i < pb.length; i++ ) {
                         var _target = target[i];
                         var _pb = pb[i];
                         addEventListener( document.getElementById(_pb), "click", set_pallet(_target, _pb), false);
                    }
                }
                {
                    var self = this;
                    each( document.getElementById( map_id ).getElementsByTagName("area"), function (item) {
                        if ( item.id ) {
                           addEventListener( item, "mousedown", function (event) {
                               if ( document.getElementById( document.getElementById( 'active_target' ).value ).style.display == "" ) {
                                  self.insert( document.getElementById( 'active_target' ).value, item.id );
                               } else if ( self.wysiwyg ) {
                                  self.wysiwyg.document.execCommand("insertImage", null, "http://" + location.host + "/img/pictogram/" + item.id + ".gif");
                               }
                           }, false);
                        }
                    }); 
                }
           },
           reset  : function (pb, target) {
                {       
                    var close_pallet = function (event) {
                         if ( event.shiftKey ) {
                            if ( isIE )
                               return false;
                            if ( event.target && event.target.tagName == "AREA" )
                               return false;
                         }       
                         if ( document.getElementById( '_pallet' ).style.display == "" ) {
                            document.getElementById( '_pallet' ).style.display = "none"; 
                            removeEventListener( document.body, "mouseup", close_pallet, false);
                         }
                    };
                }       
                {       
                    function set_pallet (_pb, _target) {
                        return function(event) {
                            var pos  = getXY(_pb);
                            var diff = isIE ? 22 : 28;
                            with ( document.getElementById( '_pallet' ).style ) {
                                display = "";
                                top     = pos.top  + diff  + "px"; 
                                left    = pos.left + "px"; 
                            }       
                            document.getElementById( 'active_target' ).value = _target;
                            setTimeout( function () {
                                addEventListener( document.body, "mouseup", close_pallet, false); 
                            }, 10); 
                        }       
                    }       
                }       
                {
                    addEventListener( document.getElementById(pb), "click", set_pallet(pb, target), false);
                }
           },
           insert : function (dist, code) {
                var code   = "{emoji:" + code + "}";
                var target = document.getElementById( dist );
                var pos = new Selection( target ).create();
                target.value = [
                             pos.before,
                             code,
                             pos.middle,
                             pos.after
                ].join("");
                {
                   /*
                      move-cursor
                   */
                   setTimeout(function () {
                       target.focus();
                       if ( target.setSelectionRange ) {
                          target.setSelectionRange( pos.before.length + code.length, pos.before.length + code.length );
                       } else if ( target.createTextRange ) {
                          var range = target.createTextRange();
                          range.move("character", pos.end + code.length);
                          range.select();
                       }    
                   }, 10);
                }
           }
    }
})();
