var BtkMenu = Class.create();

BtkMenu.prototype = {
    initialize: function(id_, options_){
        this.id         = id_;
        this.options    = this.setOptions(options_);
        this.menuItems  = new Array();

        this.isSubMenu  = false;
        if( this.options.effect && false ){
            Event.observe(window, 'load', this.initHoverEffect.bindAsEventListener(this));
        }
        Event.observe(window, 'click', this.hideThisMenu.bindAsEventListener(this));
    },
    setOptions: function(options_){
        if( !options_ ){
            options_ = {effect: true, effectMenuSilderId: 'BtkMenuSilderId'}
        }

        return options_;
    },
    registerMenuItem: function(menuItemId_, options_){
        var menuItemObj_ = new BtkMenuItem(menuItemId_, options_);
        menuItemObj_.startEvent();
        this.menuItems.push(menuItemObj_);
        Event.observe(menuItemObj_.id, 'mouseover', this.hideOthersSubMenu.bindAsEventListener(this));
    },
    hideOthersSubMenu: function(event_){
        var selectedMenuItemId_ = Event.element(event_).id;
        this.menuItems.each(function(menuItemObj_){
            if( menuItemObj_.id != selectedMenuItemId_ ){
                if( menuItemObj_.isSubMenu() ){
                    var subMenu_ = menuItemObj_.getSubMenu();
                    subMenu_.hide();
                }
            }
        });
    },
    hideThisMenu: function(event_){
        //Get the pointer x,y
        var pointerX_ = Event.pointerX(event_);
        var pointerY_ = Event.pointerY(event_);

        //If the menu is not a sub menu, do not hidden it.
        if( !this.isSubMenu )
            return false;
        if( this.isOverlapThisMenu(pointerX_, pointerY_) )
            return false;
        if( this.isOverlapSubMenu(pointerX_, pointerY_) )
            return false;

        //Hide this menu and it's sub menu
        this.hide();
    },
    setAsSubMenu: function(){
        this.isSubMenu = true;
        Event.observe(this.id, 'mouseout', this.hideThisMenu.bindAsEventListener(this));
    },
    hide: function(){
        var object_     = $(this.id);
        object_.hide();
        this.menuItems.each(function(menuItemObj_){
            if( menuItemObj_.isSubMenu() ){
                var subMenu_        = menuItemObj_.getSubMenu();
                subMenu_.hide();
            }
        });
    },
    show: function(){
        var object_     = $(this.id);
        var options_    = this.options;
        if( !options_.effect ){
            object_.show();
        }else{
            object_.setOpacity(0.0);
            object_.show();
            object_.fade({duration:1.0, from:0.0, to:1.0});
        }
    },
    initHoverEffect: function(event_){
        if( this.isSubMenu )    return;
        var options_    = this.options;
        var silderId_   = options_.effectMenuSilderId;

        var silderObj_  = $(silderId_);
        if( !Object.isElement(silderObj_) ){
            //Space for min-width used
            silderObj_  = new Element('div', {id: silderId_}).update('&nbsp;');
        }
        silderObj_.setStyle({
            width:  '100px',
            height: '20px',
            backgroundColor: '#E8E8E8'
        });
        silderObj_.setOpacity(0.6);
        silderObj_.hide();

        //Append Silder Object Into Body
        $$('body').each(function(htmlElement_){
            //Supppose only 1 body
            htmlElement_.appendChild(silderObj_);
        });

        Event.observe(this.id, 'mouseover', this.showHoverEffect.bindAsEventListener(this));
        Event.observe(silderId_, 'mousemove', this.showHoverEffect.bindAsEventListener(this));
        Event.observe(silderId_, 'mouseout', this.hideHoverEffect.bindAsEventListener(this));
        Event.observe(silderId_, 'click', this.clickHoverEffect.bindAsEventListener(this));
    },
    //When Click Hover Effect, check the menu items
    clickHoverEffect: function(event_){
        var pointerX_   = Event.pointerX(event_);
        var pointerY_   = Event.pointerY(event_);
        var selfObj_    = this;
        this.menuItems.each(function(menuItemObj_){
            var menuItemPosition_ = selfObj_.getObjectPosition(menuItemObj_.id);
            if( selfObj_.checkIsOverlap(menuItemPosition_, pointerX_, pointerY_) ){
                menuItemObj_.onClick(event_);
            }
        });
    },
    //Show Effect, when mouse hover this menu, show an action...
    showHoverEffect: function(event_){
        var pointerX_ = Event.pointerX(event_);
        var pointerY_ = Event.pointerY(event_);

        var options_    = this.options;
        var silderId_   = options_.effectMenuSilderId;

        //Get the silder
        var silderObj_  = $(silderId_);

        //Move the silder to pointer, top always = menu
        var menuPosition_   = this.getObjectPosition(this.id);
        var silderPosition_ = this.getObjectPosition(silderId_);

        var top_    = menuPosition_.top;
        var left_   = pointerX_ - (silderPosition_.width / 2);

        //if left are larger than menu, fix it
        if( (left_+silderPosition_.width) > (menuPosition_.width + menuPosition_.left) ){
            left_   = menuPosition_.width + menuPosition_.left - silderPosition_.width;
        }

        //if left are smaller than menu, fix it
        if( left_ < menuPosition_.left ){
            left_   = menuPosition_.left;
        }

        silderObj_.setStyle({
            position:   'absolute',
            top:        top_+'px',
            left:       left_+'px'
        });
        silderObj_.show();

        //Check if silder overed any menu item, if true, do the menu item mouseover effect
        var selfObj_            = this;
        var hasMenuItemOver_    = false;
        this.menuItems.each(function(menuItemObj_){
            var menuItemPosition_ = selfObj_.getObjectPosition(menuItemObj_.id);
            if( selfObj_.checkIsOverlap(menuItemPosition_, pointerX_, pointerY_) ){
                hasMenuItemOver_ = true;
                menuItemObj_.onMouseOver(event_);
            }
        });

        if( hasMenuItemOver_ ){
            silderObj_.setStyle({
                cursor: 'pointer'
            });
        }else{
            silderObj_.setStyle({
                cursor: 'auto'
            });
        }
    },
    hideHoverEffect: function(event_){
//        var pointerX_ = Event.pointerX(event_);
//        var pointerY_ = Event.pointerY(event_);

        var options_    = this.options;
        var silderId_   = options_.effectMenuSilderId;

        //Get the silder
        var silderObj_  = $(silderId_);

        //Pointer Out of the menu
        silderObj_.hide();

        //Check if silder overed any menu item, if true, do the menu item mouseout effect
        var selfObj_        = this;
        var silderPosition_ = this.getObjectPosition(silderId_);
        var silderCenterX_  = silderPosition_.left + (silderPosition_.width / 2);
        var silderCenterY_ = silderPosition_.top + (silderPosition_.height / 2);
        this.menuItems.each(function(menuItemObj_){
            var menuItemPosition_ = selfObj_.getObjectPosition(menuItemObj_.id);
            if( selfObj_.checkIsOverlap(menuItemPosition_, silderCenterX_, silderCenterY_) ){
                menuItemObj_.onMouseOut(event_);
            }
        });
    },
    isOverlapThisMenu: function(pointerX_, pointerY_){
        return this.checkIsOverlap(this.getObjectPosition(this.id), pointerX_, pointerY_);
    },
    isOverlapSubMenu: function(pointerX_, pointerY_){
        var selfObj_ = this;
        this.menuItems.each(function(menuItemObj_){
            if( menuItemObj_.isSubMenu() ){
                var subMenu_            = menuItemObj_.getSubMenu();
                var menuPositionObj_    = subMenu_.getObjectPosition(subMenu_.id);
                if( selfObj_.checkIsOverlap(menuPositionObj_, pointerX_, pointerY_) ){
                    return true;
                }
            }
        });

        return false;
    },
    checkIsOverlap: function(menuPositionObj_, pointerX_, pointerY_){
        var x1_ = menuPositionObj_.left;
        var y1_ = menuPositionObj_.top;
        var x2_ = menuPositionObj_.left +   menuPositionObj_.width;
        var y2_ = menuPositionObj_.top  +   menuPositionObj_.height;

        if( (x1_ <= pointerX_) && (pointerX_ <= x2_) &&
            (y1_ <= pointerY_) && (pointerY_ <= y2_)
        ){
            return true;
        }else{
            return false;
        }
    },
    getObjectPosition: function(objectId_){
        var object_             = $(objectId_);

        var objectDimensions_   = $(object_.id).getDimensions();
        var objectPosition_     = object_.cumulativeOffset();

        return {
            top:    objectPosition_[1],
            left:   objectPosition_[0],
            height: objectDimensions_.height,
            width:  objectDimensions_.width
        };
    },
    moveToObject: function(toObject_, position_){
        var objectPosition_ = this.getObjectPosition(toObject_);
        var selfPosition_   = this.getObjectPosition($(this.id));

        var top_    = 0;
        var left_   = 0;
        switch( position_ ){
            case "top":
                top_    = objectPosition_.top - selfPosition_.height;
                left_   = objectPosition_.left;
                break;
            case "left":
                top_    = objectPosition_.top;
                left_   = objectPosition_.left + selfPosition_.width;
                break;
            case "right":
                top_    = objectPosition_.top;
                left_   = objectPosition_.left + objectPosition_.width;
                break;
            case "bottom":
            default:
                top_    = objectPosition_.top + objectPosition_.height;
                left_   = objectPosition_.left;
        }

        $(this.id).setStyle({
            position:   'absolute',
            top:        top_+'px',
            left:       left_+'px'
        });
    }
};

var BtkMenuItem = Class.create();

BtkMenuItem.prototype = {
    initialize: function(id_, options_){
        this.id         = id_;
        this.options    = this.setOptions(options_);
    },
    setOptions: function(options_){
        if( !options_ ){
            options_ = {};
        }
        if( !options_.subMenuPosition )     options_.subMenuPosition = 'bottom';
        return options_;
    },
    startEvent: function(){
        var options_ = this.options;
//        if( options_.hoverClassName ){
//            Event.observe(this.id, 'mouseover', this.showHoverClassName.bindAsEventListener(this));
//            Event.observe(this.id, 'mouseout', this.hideHoverClassName.bindAsEventListener(this));
//        }
//        if( options_.subMenu ){
//            options_.subMenu.setAsSubMenu();
//            options_.subMenu.hide();
//
//            Event.observe(this.id, 'mouseover', this.showSubMenu.bindAsEventListener(this));
//            Event.observe(this.id, 'mouseout', this.hideSubMenu.bindAsEventListener(this));
//        }

            if( options_.subMenu ){
                options_.subMenu.setAsSubMenu();
                options_.subMenu.hide();
                Event.observe(this.id, 'mouseout', this.hideSubMenu.bindAsEventListener(this));
            }

            Event.observe(this.id, 'mouseover', this.onMouseOver.bindAsEventListener(this));
            Event.observe(this.id, 'mouseout', this.onMouseOut.bindAsEventListener(this));
//        if( options_.href ){
            Event.observe(this.id, 'click', this.onClick.bindAsEventListener(this));
//        }
    },
    setStyle: function(style_){
        $(this.id).setStyle(style_);
    },
    onMouseOver: function(event_){
        var options_ = this.options;
        if( options_.hoverClassName ){
            this.showHoverClassName(event_);
        }
        if( options_.subMenu ){
            this.showSubMenu(event_);
        }
    },
    onMouseOut: function(event_){
        var options_ = this.options;
        if( options_.hoverClassName ){
            this.hideHoverClassName(event_);
        }
        if( options_.subMenu ){
            this.hideSubMenu(event_);
        }
    },
    onClick: function(event_){
        var options_ = this.options;
        if( options_.onClick ){
            options_.onClick();
            return;
        }
        if( options_.href ){
            if( !options_.popup ){
                window.location = options_.href;
            }else{
                window.open(options_.href, '_blank');
            }
        }
    },
    showHoverClassName: function(event_){
        var options_ = this.options;
        var selfObj_ = $(this.id);
        if( options_.hoverClassName ){
            selfObj_.addClassName(options_.hoverClassName);
        }
    },
    hideHoverClassName: function(event_){
        var options_ = this.options;
        var selfObj_ = $(this.id);
        if( options_.hoverClassName ){
            if( selfObj_.hasClassName(options_.hoverClassName) ){
                selfObj_.removeClassName(options_.hoverClassName);
            }
        }
    },
    //Event Listener == Show Sub Menu on action
    showSubMenu: function(event_){
        var options_ = this.options;
        if( options_.subMenu ){
            options_.subMenu.moveToObject($(this.id), options_.subMenuPosition);
            options_.subMenu.show();
        }
    },
    //Event Listener == Hide Sub Menu on action
    hideSubMenu: function(event_){
        var options_ = this.options;
        if( options_.subMenu ){
            options_.subMenu.hideThisMenu(event_);
        }
    },
    isSubMenu: function(){
        var options_ = this.options;
        if( options_.subMenu ){
            return true;
        }else{
            return false;
        }
    },
    getSubMenu: function(){
        var options_ = this.options;
        return options_.subMenu;
    }
};