// Define com.bgc.ecm namespace
if (typeof(com) == "undefined") {
    com = { };
}
if (typeof(com.bgc) == "undefined") {
    com.bgc = { };
}
if (typeof(com.bgc.ecm) == "undefined") {
    com.bgc.ecm = { };
}

/****************************************************************************************/
/* Shortcut functions for starting and stopping the ordering with NOS and COP 
/* in a modal popup window on top of an existing page.
/*
/* Prerequisites BEFORE invoking these functions from a page: 
/* (as an example, checkout \elnino\tiles\common\orderingControllerComponent.jsp):
/*
/* 1. The invoking page must have loaded already the Prototype JS library
/* 2. The invoking page must have loaded already the JS libraries & CSS files used 
/*    for showing the popup
/* 3. The invoking page must have instantiated a globally accessible javascript variable 
/*    with name 'orderingControllerConfiguration', containing following properties:
/*    - copRootUrl: 
/*        Required! Defines the URL where the COP webapp is running
/*    - nosRootUrl: 
/*        Required! Defines the URL where the NOS webapp is running
/*    - defaultPopupWaitingPageUrl:
/*        Optional. The (preferably relative) url of the page you want to show
/*        when starting/stopping COP or NOS
/*    - presentationLanguage:
/*        Optional. The language to be used within NOS & COP. When provided, it should
/*        contain the 2-letter ISO code of a language in lower case (e.g. 'nl', 'fr', 'en').  
/*        Note that when integrating NOS or COP within a site running on a different
/*        domain (e.g. belgacomtv.be), this parameter is required, otherwise NOS
/*        and COP will not function in the same language as the main site! 
/*    - sharedSecurityDomain: 
/*        Optional. Defines the 2nd level security domain shared between the web
/*        application running in a popup and the application interacting with it. 
/*        Note that this parameter is required and needs to be the same between 
/*        the calling application and NOS and/or COP if you want receive cross-frame
/*        javascript callbacks. 
/*    - salesSegmentName:
/*        Optional. Name of the sales/site segment for which the popped up application
/*        is called. Check the SalesSegment java class in the core for valid names.
/*    - salesChannelName:
/*        Optional. Name of the sales channel for which the ordering process is
/*        invoked. Check the SalesChannel java class in the core for valid names.
/*    - onOrderingApprovedCallback( temporaryOrderId, onOrderingApprovalFinishedFunction ): 
/*        Optional. The callback function to invoke when the user approves the ordering 
/*		  of a product within NOS, before continuing the ordering within COP (= default
/*        behaviour). The id of the temporary order that has been created is passed as a
/*        parameter, as well as the function your callback should call to resume the 
/*        default behaviour of this callback. You should pass the temporary order id to
/*        this onOrderingApprovalFinishedFunction upon calling it. 
/*    - onOrderingConfirmedCallback( confirmedOrderId, originatingTemporaryOrderId ): 
/*        Optional. The callback function to invoke when the user has confirmed the 
/*        ordering within COP. The id of the final order that has been created is passed
/*        as a parameter as well as the id of the temporary order the confirmed order
/*        is originating from (i.e. the temporary order given to COP) 
/*    - onOrderingCompletedCallback:
/*        Optional. The callback function to invoke when the order has been confirmed
/*        by the user and the user closes the popup
/*    - onOrderingCancelledCallback: 
/*        Optional. The callback function to invoke when the order is not yet confirmed
/*        by the user and the user closes the popup 
/****************************************************************************************/

// na, orderingOptions & urlParams are optional parameters while productId is required
// orderingOptions is an Object of which is every property is converted into
// a single parameter. Each property can also contain a simple array value
// that gets's converted to a comma delimited list when being passed to NOS
startNosPopup = function( productId, na, orderingOptions, urlParameters ) {
	var orderingController = com.bgc.ecm.OrderingController.getInstance();
	orderingController.startNos( productId, na, orderingOptions, urlParameters );
}

stopNosPopup = function() {
	var orderingController = com.bgc.ecm.OrderingController.getInstance();
	orderingController.stopOrdering();
}

// customersSalesSegmentName is an optional parameter; if it's not passed, the default configured salesSegmentName is used.
startCopPopup = function( temporaryOrderId, customersSalesSegmentName ) {
	var orderingController = com.bgc.ecm.OrderingController.getInstance();
    orderingController.startCop( temporaryOrderId, customersSalesSegmentName );
}

stopCopPopup = function() {
	var orderingController = com.bgc.ecm.OrderingController.getInstance();
	orderingController.stopOrdering();
}

// cancel stuff
startCancelingPopup = function( cancelUrl) {
	var cancelController = com.bgc.ecm.CancelController.getInstance();
	cancelController.startCancel( cancelUrl );
}

stopCancelingPopup = function() {
	var cancelController = com.bgc.ecm.CancelController.getInstance();
	cancelController.stopCanceling();
}

/****************************************************************************************/
/* Next functions hook the NOS popup automagically to existing links
/*
/* The links can be identified by following 2 rules:
/* 1) the classname 'nosAnnotatedLink' should be assigned to the link
/* 2) the href of the link should contain at least 'productid=[dcrName]' either as such, 
/*      or either as part of a list of query parameters
/* 
/* Note that for the moment there's no support for passing an optional NA or
/* specific options when linking NOS to existing links like this. 
/****************************************************************************************/

// Define how to handle a click on a annotated link
com.bgc.ecm.onNosAnnotatedLinkClicked = function( event ) {
	var nosAnnotatedLink = Event.element(event);

	// hack in case an img is wrapped inside the link
	if (nosAnnotatedLink.tagName.toLowerCase() != 'a') {
		var nosAnnotatedLink = Event.findElement(event, 'a');
	}

	if (nosAnnotatedLink.productId) {
		startNosPopup( nosAnnotatedLink.productId );
	} else {
		alert("NOS not available, there's nothing to order!");
	}
	return true;
}

// Attach NOS Popup to all links having the 'nosAnnotatedLink' CSS classname and a productId
com.bgc.ecm.attachNosPopupToNosAnnotatedLinks = function() {
	$$("a.nosPopupLink").each( function( nosAnnotatedLink ) {
		var oldHref = nosAnnotatedLink.href.toLowerCase();
		if (oldHref.lastIndexOf('productid') > 0) {
			nosAnnotatedLink.productId = 
				oldHref.substring( oldHref.lastIndexOf('productid') ).toQueryParams().productid;
			$(nosAnnotatedLink).observe('click', com.bgc.ecm.onNosAnnotatedLinkClicked );
			nosAnnotatedLink.href = "javascript:void(0);";
		}
	} );
}

// Find all annotated links once the page is loaded
Event.observe( window, 'load', 
               function() {
                 com.bgc.ecm.attachNosPopupToNosAnnotatedLinks() 
               } );



/*******************************************************************************/
/* The OrderingController javascript class provides basic control functions
/* as well as callback hooks to interact with webapps running in a modal popup 
/* window on top of an existing page.
/*******************************************************************************/

com.bgc.ecm.OrderingController = function() {
	this.initialize.apply(this, arguments);
}

com.bgc.ecm.OrderingController.getInstance = function() {
    var activeOrderingController = com.bgc.ecm.OrderingController.current;
    if (activeOrderingController == null) {
        com.bgc.ecm.OrderingController.current = new com.bgc.ecm.OrderingController( orderingControllerConfiguration );
    }
    return com.bgc.ecm.OrderingController.current;
}

com.bgc.ecm.OrderingController.onOrderingApproved = function( temporaryOrderId, customersSalesSegmentName ) {
	if (typeof(com.bgc.ecm.OrderingController.current) != "undefined") {
		var activeOrderingController = com.bgc.ecm.OrderingController.getInstance();
		activeOrderingController.onOrderingApproved.call(activeOrderingController, temporaryOrderId, customersSalesSegmentName);
	}
}

com.bgc.ecm.OrderingController.onOrderingConfirmed = function( confirmedOrderId, originatingTemporaryOrderId ) {
	if (typeof(com.bgc.ecm.OrderingController.current) != "undefined") {
		var activeOrderingController = com.bgc.ecm.OrderingController.getInstance();
		activeOrderingController.onOrderingConfirmed.call(activeOrderingController, confirmedOrderId, originatingTemporaryOrderId);
	}
}

com.bgc.ecm.OrderingController.prototype = {
			
	initialize: function( configuration ) {
		this.configuration = configuration;
        // override default popup waiting page if one is configured
		if (this.configuration.defaultPopupWaitingPageUrl) {
			setDefaultPage( this.configuration.defaultPopupWaitingPageUrl );
		};
	},
	
	startNos: function ( productId, na, orderingOptions, urlParameters ) {
        this.productId = productId;
        this.na = na;
        this.orderingOptions = orderingOptions;
        this.urlParameters = urlParameters;

        // build default NOS invocation url with required productId parameter
        var nosPopupStartUrl = this.configuration.nosRootUrl + "/wizard/startWizard"
        							+ "/productId/" + this.productId;
        							
        // include optional na        							
        if (this.na) {
        	nosPopupStartUrl = nosPopupStartUrl + "/na/" + this.na;
        }
        
        // include optional salesChannel
        if (this.configuration.salesChannelName) {
        	nosPopupStartUrl = nosPopupStartUrl + "/salesChannelName/" + this.configuration.salesChannelName;
        }        	
    	
        // include optional salesSegment
        if (this.configuration.salesSegmentName) {
        	nosPopupStartUrl = nosPopupStartUrl + "/salesSegmentName/" + this.configuration.salesSegmentName;
        };
        
        // include optional 2nd level security domain shared between calling application & NOS
        if (this.configuration.sharedSecurityDomain) {
        	nosPopupStartUrl = nosPopupStartUrl	+ '/sharedSecurityDomain/' + this.configuration.sharedSecurityDomain;
        };

        // include optional ordering options (e.g. kind of NOS wizard to launch)
        if (this.orderingOptions) {
        	for (var aOrderingOption in this.orderingOptions) {
        		aOrderingOptionValue = this.orderingOptions[aOrderingOption];
        		// in case the value is an array, convert it to comma separated string value
        		if (aOrderingOptionValue.constructor.toString().indexOf("Array") > -1) {
        			aOrderingOptionValue = aOrderingOptionValue.join(); 
        		}
        		nosPopupStartUrl = nosPopupStartUrl	+ '/' + aOrderingOption + '/' + aOrderingOptionValue;
        	}
        };
        
        // include optional url parameters (just append it)
        if (this.urlParameters) {
        	nosPopupStartUrl = nosPopupStartUrl	+ this.urlParameters;
        };
        
        // include optional language setting if presentationLanguage has been configured
        if (this.configuration.presentationLanguage) {
        	nosPopupStartUrl = nosPopupStartUrl + '?choosed_user_language=' + this.configuration.presentationLanguage;
        };
        
        // Next block of code uses a JS closure and starts the popup indirectly to work around
        // JS objects still being "undefined" while IE loads a page and already evaluates code
        var self = this;
        this.indirectedPopupStart = setInterval( 
			function() {
	           self.indirectedPopupStart = clearInterval( self.indirectedPopupStart );
	           self.startUrlWithinPopup.call(self, nosPopupStartUrl);
            },
            100);
	},
    
	startCop: function ( temporaryOrderId, customersSalesSegmentName ) {
        if ( (temporaryOrderId == null) || (temporaryOrderId == "") ) {
        	// don't accept empty temporaryOrderId
    		alert("COP not available, there's nothing to order!");
			return;
		}
		this.temporaryOrderId = temporaryOrderId;
		
        // build default COP invocation url with required temporary order id parameter (=checkoutId)
		var copPopupStartUrl = this.configuration.copRootUrl + "/checkout.html?"
								+ "checkOutId=" + temporaryOrderId;
		
        // include optional language setting if presentationLanguage has been configured
        if (this.configuration.presentationLanguage) {
        	copPopupStartUrl = copPopupStartUrl + '&choosed_user_language=' + this.configuration.presentationLanguage;
        };

        // include optional salesChannelName
        if (this.configuration.salesChannelName) {
        	copPopupStartUrl = copPopupStartUrl + "&salesChannelName=" + this.configuration.salesChannelName;
        };

		// include customersSalesSegmentName if the parameter was passed
		// otherwise include the configured sales segment in case it's configured
		if ( (customersSalesSegmentName != null) && (customersSalesSegmentName != "") ) {
        	copPopupStartUrl = copPopupStartUrl + "&salesSegmentName=" + customersSalesSegmentName;
		} else if (this.configuration.salesSegmentName) {
        	copPopupStartUrl = copPopupStartUrl + "&salesSegmentName=" + this.configuration.salesSegmentName;
        };

        // include optional 2nd level security domain shared between calling application & NOS
        if (this.configuration.sharedSecurityDomain) {
        	copPopupStartUrl = copPopupStartUrl + "&sharedSecurityDomain=" + this.configuration.sharedSecurityDomain;
        }

        // Next block of code uses a JS closure and starts the popup indirectly to work around
        // JS objects still being "undefined" while IE loads a page and already evaluates code
        var self = this;
        this.indirectedPopupStart = setInterval( 
			function() {
				self.indirectedPopupStart = clearInterval( self.indirectedPopupStart );
				self.startUrlWithinPopup.call(self, copPopupStartUrl);
            },
            100);
	},
	
    stopOrdering: function () {
        // Next block of code uses a JS closure and stops the popup indirectly to avoid
        // problems with the stack trace being broken upon destroying objects on the call stack
        var self = this;
        this.indirectedStop = setInterval( 
            function() {
                self.indirectedStop = clearInterval( self.indirectedStop );
                self.stopPopup.call(self);
            },
            100);
    },
    
    onOrderingApproved: function( temporaryOrderId, customersSalesSegmentName ) {
    	var self = this;
        if (this.configuration.onOrderingApprovedCallback) {
            this.configuration.onOrderingApprovedCallback.call( this, temporaryOrderId, 
            													function( approvedTemporaryOrderId ) {
            														self.startCop( approvedTemporaryOrderId, customersSalesSegmentName );
            													} );
        } else {
        	this.startCop( temporaryOrderId, customersSalesSegmentName );
        }
    },

    onOrderingConfirmed: function( confirmedOrderId, originatingTemporaryOrderId ) {
    	// order confirmed => replace onOrderingCancelled with onOrderingCompleted on popup close button
    	var self = this;
    	setOnCloseFunction( function() {self.onOrderingCompleted.call(self)} );
    	if (this.configuration.onOrderingConfirmedCallback) {
    		this.configuration.onOrderingConfirmedCallback.call( this, confirmedOrderId, originatingTemporaryOrderId );
    	}
    },
    
    onOrderingCompleted: function() {
        if (this.configuration.onOrderingCompletedCallback) {
            this.configuration.onOrderingCompletedCallback.call( this );
        }
    },
    
    onOrderingCancelled: function() {
        if (this.configuration.onOrderingCancelledCallback) {
            this.configuration.onOrderingCancelledCallback.call( this );
        }
    },

    // don't call me directly, use 'startNos' or 'startCop' instead
    startUrlWithinPopup: function(url) {
        var self = this;                                
        if (isPopWinShown()) {
        	setPopWinUrl( url );
        } else {
	        showPopWin( url, 900, 620, 
                    	function() {self.onOrderingCancelled.call(self)}, true);
        }
    },
    
    // don't call me directly, use 'stop' instead
    stopPopup: function() {
        hidePopWin( false );      
    }

}




com.bgc.ecm.CancelController = function() {
	this.initialize.apply(this, arguments);
}

com.bgc.ecm.CancelController.getInstance = function() {
    var activeCancelController = com.bgc.ecm.CancelController.current;
    if (activeCancelController == null) {
        com.bgc.ecm.CancelController.current = new com.bgc.ecm.CancelController( orderingControllerConfiguration );
    }
    return com.bgc.ecm.CancelController.current;
}

com.bgc.ecm.CancelController.prototype = {

	initialize: function( configuration ) {
		this.configuration = configuration;
		if (this.configuration.defaultPopupWaitingPageUrl) {
			setDefaultPage( this.configuration.defaultPopupWaitingPageUrl );
		};
	},
	
	startCancel: function ( cancelPopupStartUrl ) {
        // Next block of code uses a JS closure and starts the popup indirectly to work around
        // JS objects still being "undefined" while IE loads a page and already evaluates code
        var self = this;
        this.indirectedPopupStart = setInterval(
			function() {
	           self.indirectedPopupStart = clearInterval( self.indirectedPopupStart );
	           self.startUrlWithinPopup.call(self, cancelPopupStartUrl);
            },
            100);
    },

    stopCanceling: function () {
        // Next block of code uses a JS closure and stops the popup indirectly to avoid
        // problems with the stack trace being broken upon destroying objects on the call stack
        var self = this;
        this.indirectedStop = setInterval(
            function() {
                self.indirectedStop = clearInterval( self.indirectedStop );
                self.stopPopup.call(self);
            },
            100);
    },

    onCancelingCompleted: function() {
        if (this.configuration.onCancelingCompletedCallback) {
            this.configuration.onCancelingCompletedCallback.call( this );
        }
    },

    onCancelingCanceled: function() {
        if (this.configuration.onCancelingCanceledCallback) {
            this.configuration.onCancelingCanceledCallback.call( this );
        }
    },

    // don't call me directly, use 'startCancel' instead
    startUrlWithinPopup: function(url) {
        var self = this;
        if (isPopWinShown()) {
        	setPopWinUrl( url );
        } else {
	        showPopWin( url, 900, 620,
                    	function() {self.onCancelingCanceled.call(self)}, true);
        }
    },

    // don't call me directly, use 'stopCanceling' instead
    stopPopup: function() {
        hidePopWin( false );
    }

}
