/**
 * controller.js
 * The purpose of this file is to observe certain DOM events and trigger an appropriate response 
 * - this saves adding listeners to specific elements and is faster if there happen to be a lot of elements to listen to
 * - this also removes the need for inline javascript code
 *
 * @date 13 Aug 2008
 * @author dePage
 */

// anything needed when the page loads should go in here
document.observe("dom:loaded", function() {
	
	// enable the ajax popup window
	if (window.ajaxWin) ajaxWin.loaded = true;
	
	Event.observe(document, 'click', cntrlr.obsrv);
	Event.observe(document, 'mouseover', cntrlr.obsrv);
	Event.observe(document, 'mouseout', cntrlr.obsrv);
	
	//setup some custom ajax responders to do global ajax stuff
	Ajax.Responders.register({        
        onCreate: function(objRequest, transport) {            
            //attach a 401 (Unauthorized) catch - we assume this is a no membername issue
            //@todo refactor this into another function which will detect if the user is logged in or needs a member name
            objRequest.options.on401 = function() {
                LazyLoad.loadJS(
                    "/js/memberName.js",
                    function() {memberName.loadDialogBox()},
                    "memberName:loaded"
                );
            };            
        }
    });
});

cntrlr = {
	
	evt:'',			// the type of event (click, mouseover, ...)
	elm:'',			// the element the event occured on
	id:'',			// the ID of the element (may be blank if the element doesn't have an ID)
	clss:'',		// the FIRST class of the element, this will start with "e_"
	debug:0,		// boolean toggle for debugging
	
	// track elements that need positioning
	positioned:[],
	
	// mouse coords 
	mX:0,
	mY:0,
	
	// the observer controller
	obsrv: function (e) {
	
		// get the classnames the element has - we'll be focusing on the FIRST classname (this part is important)
		var classes = $w(e.element().className);
		
		// switch based on the first class in the list IF it starts with "e_" (this saves a few CPU cycles)
		if (classes[0] && classes[0].startsWith('e_')) {

			// save info about the event - accessed by the methods called below
			cntrlr.clss = classes[0];
			cntrlr.setNfo(e);
			
			switch(cntrlr.clss) {
			
				/* Toggles the display of showing/hiding 2 spans within a containing div
					- stops event propagation */
				case 'e_toggle1':
					if (e.type == 'click') {
						e.stop();
						cntrlr.toggleDisplay('div', 'span');
					}
				break;
                
                case 'e_toggle2':
                    if (e.type == 'click') {
                        e.stop();
                        cntrlr.toggleDisplayNested('div', 'span');
                    }
                break;
                
                case 'e_toggle3':
                    if (e.type == 'click') {
                        e.stop();
                        // if the clicked element is an image, use the parent element
                        if (cntrlr.elm.tagName == 'IMG') {
                            cntrlr.elm = cntrlr.elm.up();
                            cntrlr.id = $(cntrlr.elm).identify();
                        }
                        cntrlr.toggleNextDiv();
                    }
                break;
				
				 case 'e_toggle3':
		                    if (e.type == 'click') {
                		        e.stop();
                        		// if the clicked element is an image, use the parent element
                        		if (cntrlr.elm.tagName == 'IMG') {
                            			cntrlr.elm = cntrlr.elm.up();
                            			cntrlr.id = $(cntrlr.elm).identify();
                        		}
                        		cntrlr.toggleNextDiv();
                    			}
                		break;
				
			
				/* Toggles the display of a popup with backing iframe */
				case 'e_dropdown':
                    if (cntrlr.id == 'languageSelector') {
                        if (e.type == 'click') {
                            e.stop();
                            cntrlr.toggleDisplayDrpdownIframe(1);
                        }
                    } else {
                        if (e.type == 'mouseover')  cntrlr.toggleDisplayDrpdownIframe(1);
                        if (e.type == 'mouseout')   cntrlr.toggleDisplayDrpdownIframe(0);
                    }
				break;
			
				/* Activates / deactivates the loupe on search result pages
					- ensures the function about to be called exists */
				case 'e_loupe':
					if (e.type == 'mouseover' && window.showLoupe) showLoupe();
					else if (e.type == 'mouseout' && window.hideLoupe) hideLoupe();
				break;
			
				/* Add / remove a file from a lightbox
					- ensures the function about to be called exists */
				case 'e_lbAdd':
				case 'e_lbDel':
				case 'e_lbAddAll':
					if (e.type == 'click') {

                        e.stop();
						if (cntrlr.clss == 'e_lbAdd' && window.lbox) lbox.init('add');
                        else if (cntrlr.clss == 'e_lbDel' && window.lbox) lbox.init('remove');
                        else if (cntrlr.clss == 'e_lbAddAll' && window.lbox) lbox.init('addAll');
					}
				break;

                //custom action - functionality is defined elsewhere - class name parameters tell us what handler class to use
                //css class name should be in format: e_custom event classname methodname [arg1 [arg2 [...]]]
                case 'e_custom':
                    //verify required number of classnames are present
                    if (classes.length < 4) {
                        return;
                    }
                    classes.shift();//we don't need first one
                    var eventType  = classes.shift();
                    var className  = classes.shift();
                    var methodName = classes.shift();
                    //only thing left in classes should be optional params
                    var aCode = [];
                    if (e.type == eventType) {
                        e.stop();
                        aCode.push("var objHandler = new " + className + "();");
                        aCode.push("objHandler." + methodName + "('" + classes.join("','") + "');");
                        //use an inspect() to see what the code looks like
                        var evalCode = new Function(aCode.join("\n"));
 			            evalCode();
                    }
                    break;

				
				// Shows / hides the custom title popup.
				case 'e_popupTitle':
					if (e.type == 'mouseover' && window.popupTitle) popupTitle.displayPopUp(cntrlr.mX, cntrlr.mY, cntrlr.elm);
					if (e.type == 'mouseout' && window.popupTitle) popupTitle.hidePopUp(cntrlr.elm);
				break;

                // Shows / hides the custom title popup. Will always show.
                case 'e_popupTitleAlwaysShow':
                    if (e.type == 'mouseover' && window.popupTitle) popupTitle.displayPopUp(cntrlr.mX, cntrlr.mY, cntrlr.elm);
                    if (e.type == 'mouseout' && window.popupTitle) popupTitle.hidePopUp(cntrlr.elm);
                break;
                
                // switch keyword copyspace
				case 'e_keywordsCopySpace':
					if (e.type == 'click'){
						// just make sure we have our code loaded
						if (keywordsCopySpace.keywordsCSObj){
							if ((keywordsCopySpace.keywordsCSlist.indexOf(cntrlr.id) != -1) && (cntrlr.id.indexOf('ajax_cs_') != -1)){
								keywordsCopySpace.changebox(cntrlr.id);
							}
						}
					}
				break;
                /**
                 ** functionality implemented but not currently live. code to support this is commented out in ajax_file_keywods|app_lib/lib_ajax_filekeywords.inc.php and master.css
                 **
                // reset keyword copyspace
                case 'e_cs_clear':
                    if (e.type == 'click'){
                        keywordsCopySpace.resetBox();
                    }
                break;
                // show/hide keyword copyspace
                case 'e_kwCopySpaceToggle':
                    if (e.type == 'click'){
                       if($('copySpaceHideShow')){
                        $('copySpaceHideShow').toggleClassName('h');
                       }
                    }
                break;
                case 'e_keywordsSensitivity':
                    if(e.type == 'click'){
                        if ($('kwSensitivity3')){
                            keywordsCopySpace.changeSensitivity(cntrlr.id);
                        }
                    }
                break;
                */
                
                // punctum day voting
                case 'e_punctumVote':
                    if (e.type == 'click'){
                        e.stop();
                        if (window.punctum) {
                            e.stop();
                            punctum.vote();
                        }
                    }
                break;
                
                // punctum day voting
                case 'e_punctumCastVote':
                    if (e.type == 'click'){
                        e.stop();
                        if (window.punctum) {
                            e.stop();
                            punctum.castVote();
                        }
                    }
                break;
                
                // close popup window
                case 'e_ajaxWinClose':
                    if (e.type == 'click'){
                        e.stop();
                        if (window.ajaxWin) {
                            ajaxWin.cancelWindow();
                        }
                    }
                break;

                /* Hiijack the click for logging in */
                case 'e_QuickSignup_Login':
                case 'e_QuickSignup_Signup':
                    
					if (e.type == 'click'){
                        controller = 'login';

                        if (cntrlr.clss == 'e_QuickSignup_Signup') {
                            controller = 'signup';
                        }

                        e.stop();
                        if (!window.quickSignupIframeHandler) {
                            LazyLoad.loadCSS('/static/css/quicksignup.css');
                            LazyLoad.loadJS(
                                "/static/js/quicksignup-bundle.js",
                                function () {quickSignupIframeHandler.loadWindow(controller);},
                                "quickSignUp:loaded");
                        } else {
                            quickSignupIframeHandler.loadWindow(controller);
                            document.fire('quickSignUp:loaded');
                        }
                    }
                break;
                //hi-jack for create a member name form
                case 'e_Quicksignup_CreateMembername':
                    if (e.type == 'click') {
                        if (typeof this.membernameChanged == 'undefined') {
                            this.membernameChanged = false;
                        }
                        
                        e.stop();      
                        if (!this.membernameChanged) {
                            LazyLoad.loadJS(
                                "/js/memberName.js",
                                function() {
                                    memberName.loadDialogBox();
                                    memberName.cancelRedirect = true;//suppress the redirect
                                    
                                    //call back function for when the change member name was a success
                                    document.observe(memberName.successEventName, function(e) {
                                        this.membernameChanged = true;                                                                        
                                        //now that we know the form has saved the new membername, let's attempt to catch it when they close the form
                                        document.observe(memberName.closeWindowEventName, function(e) {                                        
                                            //alert the world
                                            document.fire('controller:createMembernameSavedClosed');                                                                                                                      
                                        });                        
                                    });
                                },
                                "memberName:loaded"
                            );
                        } else {
                            //we have already shown the form and changed the member name, no sense in keep showing it
                            document.fire('controller:createMembernameAlreadySaved');
                        }
                    }
                    break;
                /* Creates a popup when clicking the ? image on Extended License downloads (Indemnification) */
                case 'e_Indemnification':
                    if (e.type == 'click'){
                        e.stop();

                        if (window.IndemnificationAjax) {
                            IndemnificationAjax.indemnificationAJAX();
                        }
                    }
                break;

			}
		}
	},
	
	// store the info about the event so other JS methods can access it
	setNfo: function(e) {
	
		// set mouse coords
		cntrlr.mX = Event.pointerX(e);
		cntrlr.mY = Event.pointerY(e);

		// set event properties
		cntrlr.elm = e.element();
		cntrlr.evt = e.type;
		cntrlr.id = $(cntrlr.elm).identify();
		
		// debugging output
		if (cntrlr.debug && window.console) {
			console.log('EVT:'+cntrlr.evt+' - ID:'+cntrlr.id+' - CLASS: '+cntrlr.clss+' - ELM:'+cntrlr.elm);
		}
	},
	
	// function to toggle the visibility of two spans within a parent div
	toggleDisplay: function(parnt, chldn) {
		var prntElm = $(cntrlr.elm).up(parnt);
		prntElm.down(chldn).toggle();
		prntElm.down(chldn).next(chldn).toggle();
	},
	
	
	// function to toggle the visibility of two spans within a parent div
	toggleDisplayNested: function(parnt, chldn) {
		var childElm = $(cntrlr.elm).up(chldn);
		var prntElm = childElm.up(parnt);
		prntElm.down(chldn).toggle();
		prntElm.down(chldn).next(chldn).toggle();
	},
    
    // function to toggle the display of the next div down in the DOM & to toggle the more/less arrow too
    toggleNextDiv: function() {
        var trgtImg = $(cntrlr.elm).down('img');
        var trgtDiv = $(cntrlr.elm).next('div');
        $(trgtImg).toggleClassName('ico_more').toggleClassName('ico_less');
        Effect.toggle(trgtDiv, 'blind', {duration:.3});
    },
	
	// function to toggle the display of the next div down in the DOM & to toggle the more/less arrow too
	toggleNextDiv: function() {
		var trgtImg = $(cntrlr.elm).down('img');
		var trgtDiv = $(cntrlr.elm).next('div');
		$(trgtImg).toggleClassName('ico_more').toggleClassName('ico_less');
		Effect.toggle(trgtDiv, 'blind', {duration:.3});
	},	
	
	// function to show/hide the visibility of a div that's backed by an iframe
	toggleDisplayDrpdownIframe: function(toggle) {
    
        var dropdownID = cntrlr.id+"Dropdown";
        var iFrameID = cntrlr.id+"Iframe";
        
        // modified behavior for the languageSelector - we fork on this param in a lot of cases
        var isLanguageSelector = (cntrlr.id == 'languageSelector') ? true : false;
        
        // ensure required divs exist
        if (! $(dropdownID)) return;
        
        // the very first time we show the popup we need to create a div, position the dropdown and the iFrame beneath (this makes the dropdown faster in subsequent accesses)
        if (toggle && cntrlr.positioned && !cntrlr.positioned[cntrlr.id]) {
            
            // create the iframe, append to #wrapper div (at the bottom)
            if (!$(iFrameID)) $('wrapper').insert({bottom:'<iframe id="'+iFrameID+'" style="display:none; z-index:5000; position:absolute; border:0; background:#fff"></iframe>'});
                    
            // position the dropdown div - all browsers except the IE6+7 respect a 0 offsetLeft parameter. IE needs a lot more love: ensure the parent exists and has properties
            // all dropdowns except the language selector are 20 px lower
            var offsetTop = (isLanguageSelector) ? 0 : 20;
            try {
                if (Prototype.Browser.IE) Element.clonePosition(dropdownID, cntrlr.id, {setWidth:false, setHeight:false, offsetLeft:-3, offsetTop:offsetTop});
                else Element.clonePosition(dropdownID, cntrlr.id, {setWidth:false, setHeight:false, offsetLeft:0, offsetTop:offsetTop});
            } catch (e) {
                // IE throws an error when clone is used the first time, so run it again (known PrototypeJS issue)
                Element.clonePosition(dropdownID, cntrlr.id, {setWidth:false, setHeight:false, offsetLeft:-3, offsetTop:offsetTop});
            }
            
            // HACK: IE6 + FF2 gives the dropdown element a nasty width, so explicitly set it here (seems like it knows its width but doesn't know its width)
            var dw = $(dropdownID).getWidth()+'px';
            var ddDims = $(dropdownID).getDimensions();
            $(dropdownID).setStyle({
                width:ddDims['width']+'px',
                height:ddDims['height']+'px'
            });
            
            // position the iframe & ensure the iframe has the same dims as the dropdown (the extra 26px is for the padding + border on the dropdn class)
            if (Prototype.Browser.IE) Element.clonePosition(iFrameID, cntrlr.id, {setWidth:false, setHeight:false, offsetLeft:0, offsetTop:offsetTop});
            else Element.clonePosition(iFrameID, cntrlr.id, {setWidth:false, setHeight:false, offsetLeft:0, offsetTop:offsetTop});
            var ieWidthFix = (Prototype.Browser.IE) ? 4 : 5;
            $(iFrameID).setStyle({
                width:ddDims['width'] + ieWidthFix +'px',
                height:ddDims['height']+'px'
            });
            
            // HACK: becuase of the iframe and border requirements we need a new div with a 3px height located top-left corner of the dropdown div
            // but we only need this for non-languageSelector dropdown instances
            if (!isLanguageSelector) {
                var ieFixW = (Prototype.Browser.IE) ? 0 : 6;
                var barWidth = $(dropdownID).getWidth() - $(cntrlr.id).getWidth() + ieFixW;
                $(dropdownID).insert({top:'<div style="float:right; height:0; line-height:0; width:'+barWidth+'px; border-top:solid 3px #f2f2f2; margin-right:-10px; z-index:5000"></div>'});
            }
        
            // set divs as positioned
            cntrlr.positioned[cntrlr.id] = true;
        }
    
        // show or hide elements as needed, remove then add event listeners
        if (toggle && !$(dropdownID).visible()) {
            
            $(dropdownID).show();
            $(iFrameID).show();
            
            // set an observer to catch a mouseout of this div to close it
            Event.observe($(dropdownID), 'mouseover', function() {
                if (!isLanguageSelector) $(cntrlr.id).addClassName('headerTabActive');
                $(dropdownID).show();
                $(iFrameID).show();
            });
            
            // HACK: IE5.5+ causes flickering for mouseout, so we'll listen for mouseleave
            // dunno if this is gonna work on IE9 (IE8 is out at time of writing)
            var mouseOutEvt = (Prototype.Browser.IE) ? 'mouseleave' : 'mouseout';
            Event.observe($(dropdownID), mouseOutEvt, function(ev) {
                
                if (!isLanguageSelector) $(cntrlr.id).removeClassName('headerTabActive');
                $(dropdownID).hide();
                $(iFrameID).hide();
            });
            
        } else if ($(dropdownID).visible()) {
            $(dropdownID).hide();
            $(iFrameID).hide();
        }
    }
}
