/**
 * class taking care that only one embed menu is visible
 * 
 * @author joko
 */
var EmbedHandler = new Class({
        Implements: [Options],
        
        initialize: function(menus){
            this.menus = menus;
        },
        
        setEmbedMenu: function(menu){
            this.menus.include(menu);
        },
        
        hideOpen: function(dontHide){
            this.menus.each(function(menu){
                if(menu != dontHide){
                    menu.hide();
                }
            });
        }
});


/**
 * class for creating embed menus
 * 
 * @author joko
 */
var EmbedMenu = new Class({
        Implements: [Options],
        options: {
            delayOpen: 500,
            delayClose: 500,
            opacity: 1.0,
            offsetX: 1,                                             // modify menu offset to the left/right
            offsetY: 0,                                             // modify menu offset to the top/bottom
            borderDistance: 5,
            expandIndicator: false,                                 // small symbol that indicates that menu is expandable / collapsible
            width: "500px",
            
            menuCustomizeCSS: {
                "opacity":              0,
                "position":             "absolute",
                "border":               "1px solid lightgrey",
                "height":               "auto",
                "background-color":     "#FFFFFF",
                "text-align":           "left",
                "padding-bottom":       "25px"
            },
            
            effectOptions: {
                duration: 30,
                transition: Fx.Transitions.linear
            },
            
            minOffset: 5,                                               // prevent that embed menu is out of visible area
            bindMenu: false,                                          // create a small div that frames the element
            closeOnBlur: true                                         // workaround to close menu if user clicks beside menu
        },
        
        initialize: function(element,options){
            
            this.element = null;
            this.menu = null;                                       // outer menu
            this.menuContent = null                                 // menu content (loaded via ajax)
            this.overlayElement = null;                             // div which frames link
            this.embedHandler = null;                               // embed handler
            this.clickableArea = null;
            
            //check and set options
            this.setOptions(options);
            this.element = $(element);
            
            if(this.options.expandIndicator){
                this.element.getElement("a").getElement("span").grab(new Element("span").set("id", "expandable").set("text", " ▼"));
            }
            
            this.menu = this.createEmbedMenu();                     //outer menu
            this.menu.inject(document.body);
            
            // bind menu to element (creates a small div that frames the element)
            if(this.options.bindMenu){
                this.overlayElement = this.bindObjectToMenu();
                this.overlayElement.inject(this.element);
            }

            //only toggle if link is clicked
            this.element.getElement("a").addEvent("click",function(event){
                event.stop();
                this.toggle();
            }.bindWithEvent(this));
            
            window.addEvent('resize',this.doPosition.bind(this));
            
            $(window.document).addEvent("keydown",function(event){
                if(event.key == "esc"){ 
                    this.hide(); 
                }
            }.bindWithEvent(this));
        },
        
        createEmbedMenu: function(){
            // create main menu layer and set Styles
            return new Element("div").setStyles(this.options.menuCustomizeCSS).setStyle("width",this.options.width);
        },
        
        /**
         * show Menu
         */
        show: function(){
            if(!this.menuContent){
                this.menuContent = new Element("div",{
                    "text":"Loading..."
                }).inject(this.menu).set("tween",this.options.effectOptions);
                
                var append = "?ajax";
                if(this.element.getElement("a").get("href").contains("/?")){
                    append = "&ajax";
                }
                
                new Request({
                    "url": this.element.getElement("a").get("href")+append,
                    onComplete: function(response){
                        this.menu.innerHTML = response; 
                        this.doPosition();
                    }.bind(this)
                }).send();
            }
            
            // close embedMenu when clicking somewhere next to it
            var bodySize = $(document.body).getSize();
            var scroll = $(window).getScroll();
            this.clickableArea = new Element("div",{
                "style":"z-index:1;opacity:0.0;filter: alpha(opacity = 0);width:"+(bodySize.x+scroll.x)+"px;height:"+(bodySize.y+scroll.y)+"px;position:absolute;top:0;left:0;background-color:#FFFFFF;"}
            ).addEvent("click",function(){
                this.toggle();
                this.clickableArea.dispose();
            }.bindWithEvent(this)).inject(document.body);            
            
            this.shown = true;
            this.doPosition();
            this.element.setStyle("z-index", 100);
            this.menu.setStyle("z-index", 10);
            this.menu.tween("opacity",this.options.opacity);
            
            
            
            if(this.options.bindMenu){
                this.overlayElement.set("tween",this.options.effectOptions).tween("opacity",this.options.opacity);
            }
            
            // collapse symbol
            if(this.options.expandIndicator){
                $("expandable").set("text"," ▲");
            }
            
            // hide other embed menus
            if(this.embedHandler){
                this.embedHandler.hideOpen(this);
            }
            
            return this;
        },
        
        /**
         * hide Menu
         */
        hide: function(){
            this.shown = false;
            this.menu.tween("opacity","0.0");
            if(this.options.bindMenu){
                this.overlayElement.set("tween",this.options.effectOptions).tween("opacity","0.0");
            }
            
            // be sure that clickable background does not exist anymore
            if(this.clickableArea){
                this.clickableArea.dispose();
            };
            
            // expand symbol
            if(this.options.expandIndicator){
                $("expandable").set("text"," ▼");
            }
            return this;
        },
        
        /**
         * toggle Menu
         */
        toggle: function(){
            return (this.shown) ? this.hide() : this.show();
        },
        
        /**
         * align menu to element
         */
        doPosition: function(){
            // calculate positions for embed-menu
            var coordinates = this.element.getCoordinates();//alert(coordinates.left);
            var absLeft  = coordinates.left - (this.menu.getStyle("width").toInt() - this.element.getSize().x) + this.options.offsetX;
            var absTop = coordinates.top + this.element.getSize().y + this.options.offsetY;
            
            if(absLeft < this.options.minOffset){
                absLeft = this.options.minOffset;
            }
             // set position of embed-menu
            this.menu.setStyles({
                left: absLeft + "px",
                top: absTop + "px"
            });
            
            if(this.options.bindMenu){
                coordinates = this.element.getCoordinates();
                absLeft  = coordinates.left - this.options.borderDistance + this.options.offsetX;
                absTop = coordinates.top - this.options.borderDistance + this.options.offsetX;
                
                this.overlayElement.setStyles({
                    left: absLeft + "px",
                    top: absTop + "px"
                });
            }
        },
        
        bindObjectToMenu: function(){
            return new Element("div").setStyles({
                opacity: 0,
                "z-index": -1,
                position: "absolute",
                width: (this.element.getSize().x + this.options.borderDistance) + "px",
                height: (this.element.getSize().y + this.options.borderDistance) + "px",
                border: "1px solid lightgrey",
                "border-style": "solid solid none",
                "background-color": "#FFFFFF"
            });
        },
        
        /**
         * set embed handler
         */
        setEmbedHandler: function(handler){
            this.embedHandler = handler;
        }
});

