/*
 * Copyright (C) 2005 - 2011 Jaspersoft Corporation. All rights reserved.
 * http://www.jaspersoft.com.
 *
 * Unless you have purchased  a commercial license agreement from Jaspersoft,
 * the following license terms  apply:
 *
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License  as
 * published by the Free Software Foundation, either version 3 of  the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero  General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public  License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */


///////////////////////////////////////////////////////////////////////////////////
// Core Event Handlers
///////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////
// MouseDown
///////////////////////////////////////////////////////////////////////////////////

/**
 * General mouse down event tracking
 */
document.observe('mousedown', function(evt) {
    var primaryPanel ;
    var element = evt.element();

    if (element.match(layoutModule.MINIMIZED_PATTERN)) {
        layoutModule.maximize(element);
        return;
    }

    if (element.match(layoutModule.MINIMIZER_PATTERN)) {
        layoutModule.minimize(element);
        return;
    }

    //for meta links
    if(element.match(layoutModule.META_LINKS_PATTERN)){
        if(element.readAttribute("id") === "main_logOut_link"){
            primaryNavModule.navigationOption("logOut");
        }
    }

    //for any button type element (including list/tree items, menu items, toolbar buttons and tabs)
    var matched = matchAny(element, [layoutModule.BUTTON_PATTERN, layoutModule.MENU_LIST_PATTERN ], true);
    if (matched && !$(matched).match(layoutModule.PRESSED_PATTERN)) {
        buttonManager.down(matched);
    }

    //APC notes: disclosure events can never get here (noBubble). Delete?
    if (element.match(layoutModule.DISCLOSURE_BUTTON_PATTERN)) {
        buttonManager.down(element);
    }
});


///////////////////////////////////////////////////////////////////////////////////
// MouseOver
///////////////////////////////////////////////////////////////////////////////////

/**
 * General mouse over event tracking
 * @param draggable
 */
document.observe('mouseover', function(evt){
    var element = evt.element();
    var matched = null;

    //for navigation buttons
    matched = matchMeOrUp(element, layoutModule.NAVIGATION_MUTTON_PATTERN);
    if (matched && !relatedTargetInElementSubtree(evt,matched)) {
        primaryNavModule.showNavButtonMenu(evt, matched);
        //TODO: clean up
        matched.tabIndex = -1;
        matched.focus();
    }

    if (!isIE7()) {
		//for any button type element (including list/tree items, menu items, toolbar buttons and tabs)
		matched = matchAny(element, [layoutModule.BUTTON_PATTERN], true);
		if (matched && !relatedTargetInElementSubtree(evt, matched) && !matched.hasClassName(layoutModule.DROP_TARGET_CLASS)) {
			buttonManager.over(matched);
		}

		//APC notes: disclosure events can never get here (noBubble). Delete?
		//TODO: Remove this!!!!
		if (element.match && element.match(layoutModule.DISCLOSURE_BUTTON_PATTERN)) {
			buttonManager.over(element);
		}
	}
});

///////////////////////////////////////////////////////////////////////////////////
// MouseOut
///////////////////////////////////////////////////////////////////////////////////

/**
 * General mouse out event tracking
 * @param draggable
 */
if(!isIE7()) {
	document.observe('mouseout', function(evt){
	    var matched = null;
	    var element = evt.element();

	    //for any button type element (including list/tree items, menu items, toolbar buttons and tabs)
	    matched = matchAny(element, [layoutModule.BUTTON_PATTERN],true);
	    if(matched && !relatedTargetInElementSubtree(evt,matched)){
	        buttonManager.out(matched);
	    }

	    //APC notes: disclosure events can never get here (noBubble). Delete?
	    //TODO: Remove this!!!!
	    if (element.match && element.match(layoutModule.DISCLOSURE_BUTTON_PATTERN)) {
	        buttonManager.out(element);
	    }
	});
}

///////////////////////////////////////////////////////////////////////////////////
// MouseUp
///////////////////////////////////////////////////////////////////////////////////

/**
 * General mouse up event tracking
 */
document.stopObserving('mouseup').observe('mouseup', function(evt){


    var element = evt.element();
    var matched = null;

    matched = matchMeOrUp(element, layoutModule.NAVIGATION_PATTERN);
    if (matched){
        if(matched.identify() == layoutModule.MAIN_NAVIGATION_HOME_ITEM_ID){
            primaryNavModule.navigationOption("home");
        }else{
            return;
        }
    }

    //for general tab-set tabs
    //TODO: If we use 'pressed' class instead of 'selected' class we can use existing buttonMgr down() and up() handlers
    //instead
    matched = matchMeOrUp(element, layoutModule.TABSET_TAB_PATTERN);
    if(matched/* && matched.match(layoutModule.BUTTON_PATTERN)*/) {
        if (!$(matched).match(layoutModule.SELECTED_PATTERN)){
            $(matched).siblings().each(function(object) {
                buttonManager.unSelect($(object));
            });
            buttonManager.select($(matched));
        }
    }

    //for any button type element (including list/tree items, menu items, toolbar buttons and tabs)
    matched = matchAny(element, [layoutModule.BUTTON_PATTERN,layoutModule.BUTTON_SET_BUTTON, layoutModule.MENU_LIST_PATTERN ], true);
    if (matched && !matched.match(layoutModule.TOOLBAR_CAPSULE_PATTERN)) {
        buttonManager.up(matched);
    }

    //APC notes: disclosure events can never get here (noBubble). Delete?
    //TODO : remove this code!!!
    if (element.match && element.match(layoutModule.DISCLOSURE_BUTTON_PATTERN)) {
        buttonManager.up(element);
    }

    if (isRightClick(evt)) {
        var node = evt.element();
        document.fire(layoutModule.ELEMENT_CONTEXTMENU, { targetEvent: evt, node: node});
    }


});

///////////////////////////////////////////////////////////////////////////////////
// Drag with MouseDown
///////////////////////////////////////////////////////////////////////////////////

document.observe('drag:mousedown', function(evt) {
    var element = evt.memo.targetEvent.element();

    var li = matchMeOrUp(element, layoutModule.LIST_ITEM_PATTERN);
    if (li && !element.match(layoutModule.DISCLOSURE_BUTTON_PATTERN)) {
        buttonManager.down(li, function(element) {
            return $(element).down(layoutModule.LIST_ITEM_WRAP_PATTERN);
        });
    }

    if (element.match(layoutModule.DISCLOSURE_BUTTON_PATTERN)) {
        buttonManager.down(element);
    }

	//stopTimer('mousedown');

});


///////////////////////////////////////////////////////////////////////////////////
// Mouse Effects
///////////////////////////////////////////////////////////////////////////////////

var buttonManager = {

    over: function(element, findTargetFn) {
        if (element && !this.isSelected(element)) {
            var target  = findTargetFn ? findTargetFn(element) : element;
            $(target).addClassName(layoutModule.HOVERED_CLASS);
        }
    },

    out: function(element, findTargetFn) {
        if (element) {
            var target  = findTargetFn ? findTargetFn(element) : element;
            $(target).removeClassName(layoutModule.HOVERED_CLASS).removeClassName(layoutModule.PRESSED_CLASS);
        }
    },

    down: function(element, findTargetFn) {
        if (element && !this.isSelected(element)) {
            var target  = findTargetFn ? findTargetFn(element) : element;
            $(target).removeClassName(layoutModule.HOVERED_CLASS).addClassName(layoutModule.PRESSED_CLASS);
        }
    },

    up: function(element, findTargetFn) {
        if (element && !this.isSelected(element)) {
            var target  = findTargetFn ? findTargetFn(element) : element;
            $(target).removeClassName(layoutModule.PRESSED_CLASS).addClassName(layoutModule.HOVERED_CLASS);
        }
    },

    disable: function(element) {
        if (element) {
            buttonManager.out(element);
            $(element).writeAttribute(layoutModule.DISABLED_ATTR_NAME, layoutModule.DISABLED_ATTR_NAME);
        }
    },

    enable: function(element) {
        if (element) {
            buttonManager.out(element);
            $(element).writeAttribute(layoutModule.DISABLED_ATTR_NAME, null);
        }
    },

    /**
     * @deprecated custom jasperhandler in Prototype.js will suppress disabled elems
     * @param {Object} element
     */
    isDisabled: function(element) {
        if (element) {
            return $(element).readAttribute(layoutModule.DISABLED_ATTR_NAME) === layoutModule.DISABLED_ATTR_NAME ||
                    $(element).hasClassName(layoutModule.DISABLED_CLASS);
        }
    },

    ///////////////////////////////////////////////////////////////////////////////////////
    // TODO: Only used by tab manager - maybe we should use up and down functions instead.
    // (just need to make tabs use 'pressed' class instead of 'selected')
    ///////////////////////////////////////////////////////////////////////////////////////


    unSelect : function(element){
        if(element){
            $(element).removeClassName(layoutModule.SELECTED_CLASS);
        }
    },


    select : function(element){
        if(element){
            $(element).addClassName(layoutModule.SELECTED_CLASS);
        }
    },

    isSelected : function(element, findTargetFn){
        if(element){
            var target  = findTargetFn ? findTargetFn(element) : element;
			var tagetListItem = target.up('li');
            return tagetListItem && tagetListItem.hasClassName(layoutModule.SELECTED_PATTERN);
        }

        return false;
    }
};



///////////////////////////////////////////////////////////////////////////////////
// Suppress Default Context Menu
///////////////////////////////////////////////////////////////////////////////////

//use this to cancel the default event. Weird behavior on mac Gecko browser
//see link:http://unixpapa.com/js/mouse.html for more info
document.observe('contextmenu', function(event) {
    Event.stop(event);
    return false;
});
