//convenience fn creates new controller object and calls triggerAddRequest
var suitcaseControllerInstance = undefined;

function addToSuitcase(itemType, itemId) {
	if (suitcaseControllerInstance == undefined) {
		suitcaseControllerInstance = new SuitcaseController();	
	}
    suitcaseControllerInstance.triggerAddRequest(itemType, itemId);
}


var SuitcaseController = Class.create();
SuitcaseController.prototype = {
    ITEM_ID_PARAM : "objectId",
    ITEM_TYPE_PARAM : "objectType",
    RETURN_TO_PARAM: "returnToURL",
    PARENT_RETURN_TO_PARAM: "parentReturnToURL",
    DYNAMIC_SUITCASE_FORM: "dynamicSuitcaseForm",
    PROGRESS_WIDGET_ID: "suitcaseProgressWidget",
    PROGRESS_MESSAGE_TEXT_ID: "suitcaseProgressWidgetText",
    ITEM_XML_URL: "/suitcase/ajax/additem",
    COOKIE_NAME: "k_so",

    RESPONSE_CODE_OK: "OK",
    RESPONSE_CODE_ERROR_PARAMS: "FAIL_PARAMS",
    RESPONSE_CODE_ERROR_LOGIN: "FAIL_LOGIN",
    RESPONSE_CODE_ERROR_GENERAL: "FAIL_GENERAL",

    RESPONSE_EXCEPTION_PROP : "exception",
    RESPONSE_XML_PROP : "addItemXml",
    LOGIN_EXCEPTION_TYPE : "loginException",
    GENERAL_EXCEPTION_TYPE : "generalException",
    OBJECTNOTFOUND_EXCEPTION_TYPE : "objectNotFoundException",
    DEFAULT_ERROR : "There was an error adding the selected item to your suitcase. Please try again.",
    COOKIE_ERROR : "In order to use Suitcase, you must have cookies enabled in your browser.",
    NO_ACTION_URL_ERROR : "You are currently not logged in or registered. Please log-in before adding items to your suitcase",
    OBJECTNOTFOUND_ERROR: "Sorry, but this item can not be added to your suitcase at this time.",
    PROCESSING_ERROR: "We're sorry, but there was an error in processing your request. Please try again later.",
    SUITCASE_ADD_MESSAGE: "Adding to Suitcase",
	    NOT_LOGGED_IN_ERROR: "You must be logged in to add items to your suitcase. . . forwarding to log-in page.",


    //LOGIN_REG_URL: "user/suitcase/login",
    //suitcaseForwardURL: "http://suitcase.concierge.com",

    requestActive: false,
    statusMessageActive: false,
    conciergeRootURL: "http://" + window.location.host,
    ajaxRequestRef: undefined,
    itemXmlResponse: undefined,

    initialize: function() {
	    //Event.observe(document.body, "onscroll",  this.scrollProgressMessage.bindAsEventListener(this) ); 
	    //Event.observe(document.body, "DOMMouseScroll",  this.scrollProgressMessage.bind(this) ); 
	    //window.onmousewheel = document.onmousewheel = this.scrollProgressMessage.bindAsEventListener(this);
	   
    },
    
    scrollProgressMessage: function(event) {
	    if (this.statusMessageActive && $(this.PROGRESS_WIDGET_ID) != undefined) {
		this.redrawProgressWidget($(this.PROGRESS_WIDGET_ID));    
	    }
    },

    buildConciergeURL: function(path) {
        return (this.conciergeRootURL + path);        
    },

    cookiesEnabled: function() {
	if (window.navigator.cookieEnabled) {
		//alert ("Cookies enabled: " + window.navigator.cookieEnabled);
		return true;
	}
        var canReadCookies = (((document.cookie != undefined && (document.cookie.indexOf(this.COOKIE_NAME) != -1)) ) ? true : false);  
	//alert ("Cookies: " + navigator.cookieEnabled);
	if (!canReadCookies) {
		//let's do a quick test
		document.cookie = "tempCookie=temp; "; // if we get here, document.cookie is already undefined
		canReadCookies = ((document.cookie.indexOf("tempCookie") != -1) ? true : false); 
		//alert ("can read cookies: " + canReadCookies);
	}
	return canReadCookies;
    },
    
    setProgressMessage: function(messageText) {
	var messageSpan = $(this.PROGRESS_MESSAGE_TEXT_ID);   
	messageSpan.removeChild(messageSpan.lastChild);
	var message = document.createTextNode(messageText);
	messageSpan.appendChild(message);
	//alert("Set message..." + messageText);
    },

    showError: function(errorMessage) {
        this.statusMessageActive = true;
        var message = "";
	if (errorMessage == undefined) {
            message = (this.DEFAULT_ERROR);    
        } else {
           message = errorMessage;
        }
	var progressWidget = $(this.PROGRESS_WIDGET_ID);
	if (progressWidget == undefined) {
		progressWidget = this.createProgressWidget(message);    
	} else {
		this.setProgressMessage(message);    
	}
	this.redrawProgressWidget(progressWidget);
	this.startWidgetTimeout(progressWidget);
    },
    
    clearWidget: function() {
	 this.statusMessageActive = false;
	 var progressWidget = $(this.PROGRESS_WIDGET_ID);
	 if (progressWidget != undefined) {
		progressWidget.style.display = "none";   
		//Element.hide(progressWidget);	 
	 }
    },
    
    startWidgetTimeout: function(widget) {
	    setTimeout(this.clearWidget.bind(this), 20000);
    },
    
    createProgressWidget: function(messageText) {
	var dynamicWidget = document.createElement("DIV");
	dynamicWidget.id = this.PROGRESS_WIDGET_ID;
	//dynamicWidget.setAttribute("ID", this.PROGRESS_WIDGET_ID);
	var messageSpan = document.createElement("SPAN");
	var message = document.createTextNode(messageText);
	messageSpan.id = this.PROGRESS_MESSAGE_TEXT_ID;
	//messageSpan.setAttribute("ID", this.PROGRESS_MESSAGE_TEXT_ID);
	messageSpan.appendChild(message);
	dynamicWidget.appendChild(messageSpan);
	document.body.appendChild(dynamicWidget);

	dynamicWidget.className = "suitcasestatus";
	dynamicWidget.style.width = ((document.body.offsetWidth ? document.body.offsetWidth : window.innerWidth) + "px"); //override width
	//Element.addClassName($(this.PROGRESS_MESSAGE_TEXT_ID), "suitcasestatusmessage");
	messageSpan.className = "suitcasestatusmessage"; 
	setInterval(this.scrollProgressMessage.bindAsEventListener(this), 10); // this keeps the widget on top
	return dynamicWidget;
    },
    
    disableExitPop: function() {
	    noPopFlag = true;
	    Try.these(function() {
	    if (window.opener) {
		window.opener["noPopFlag"] = true;    
	    }}
	    );
	
	    /**
	    ext = (window.ext ? window.ext : (window.opener && window.opener.ext ? window.opener.ext : undefined));
	    if (ext != undefined) {
		    ext.monitorEnabled = false;
	    }
	    **/
    },
    
    redrawProgressWidget: function(progressWidget) {
	  var scrollOffset = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop;
	  if (scrollOffset != undefined) {
	      progressWidget.style.top = scrollOffset + "px";
	  } else {
	      progressWidget.style.top = "0px"; 	  
	  }
	  var messageSpan = $(this.PROGRESS_MESSAGE_TEXT_ID);
	  if (messageSpan != undefined) {
		  messageSpan.style.width = (document.body.offsetWidth ? document.body.offsetWidth : window.innerWidth) + "px";	  
	  }
	  progressWidget.style.width = (document.body.offsetWidth ? document.body.offsetWidth : window.innerWidth) + "px";
	  progressWidget.style.display = "block";  
	  //alert("Redrawing progresswidget: This is not an error -- please ignore this message in tests");
    },

    displayProgressWidget: function(activeState) {
	    var progressWidget = $(this.PROGRESS_WIDGET_ID);
	    if (progressWidget == undefined) {
		progressWidget = this.createProgressWidget(this.SUITCASE_ADD_MESSAGE);    
	    } else {
		this.setProgressMessage(this.SUITCASE_ADD_MESSAGE);    
	    }
        if (activeState) {
            //todo: add start widget animation here. 
	    this.redrawProgressWidget(progressWidget);
	    this.startWidgetTimeout(progressWidget); // we add a timeout, since we have removed the clearWidget from onComplete eventListener
        } else {
            //todo: add stop widget animation here. 
	    this.statusMessageActive = false;
	    progressWidget.style.display = "none";
	    //Element.hide(progressWidget);
        }
    },

    triggerAddRequest: function(itemType, itemId) {
        if (!this.cookiesEnabled()) {
            // cookies not enabled -- abort!!
            this.showError(this.COOKIE_ERROR);
            return;
        }

        if (this.requestActive) {
            //abort, request is already occurring
            this.showError("We are currently adding an item to your suitcase. Only one item can complete concurrently");
            return;
        }

        this.requestActive = true; //ensures only single add at a time
	this.statusMessageActive = true; // tracks that the status message is displayed
        var submitURL = this.buildConciergeURL(this.ITEM_XML_URL);
        var returnToURL = document.location;
	//capture parent URL
	var parentReturnToURL = undefined;
	if (window.opener) {
		parentReturnToURL = window.opener.location;	
	}
        var queryString = 
            this.ITEM_ID_PARAM + "=" + itemId + 
            "&" + this.ITEM_TYPE_PARAM + "=" + itemType +
            "&" + this.RETURN_TO_PARAM + "=" + escape(returnToURL) + 
	    (parentReturnToURL != undefined ? ("&" + this.PARENT_RETURN_TO_PARAM + "=" + escape(parentReturnToURL)) : "");

        //set parameters for this request
        var opt = {
            method: 'post',
            parameters: queryString,
            onSuccess: this.onSuccess.bind(this),
            onComplete: this.onComplete.bind(this),
            onFailure: this.onFailure.bind(this),
            onException: this.onException.bind(this)
        }

        this.displayProgressWidget(true);
	document.body.style.cursor = "progress";
//alert("this.ajaxRequestRef = new Ajax.Request(" + submitURL + ", opt params=" + queryString + ")");
        this.ajaxRequestRef = new Ajax.Request(submitURL, opt);
    }, 

    onFailure: function(response) {
        this.requestActive = false;
        this.showError(this.DEFAULT_ERROR);
    },

    onComplete: function(response) {
        document.body.style.cursor = "auto";
	//this.displayProgressWidget(false);
    },
 
    onException: function(ajaxRequestObj, exception) {
        this.requestActive = false;
        errorMsg = "";
	for (i in exception) {
		errorMsg = errorMsg + i + ": " + exception[i] + "  ";	
	}
	alert("onException: " + errorMsg);
	this.showError(this.PROCESSING_ERROR + ": " + errorMsg);
	
    },

    onSuccess: function(response) {
        this.requestActive = false;

        var json = eval("(" + response.responseText + ")");
        if (json == undefined) {
            this.showError(this.PROCESSING_ERROR);
            return;
        }
//alert("json.objectId=" + json.objectId + ", objectType=" + json.objectType + ", action=" + json.action + ", responseCode=" + json.responseCode + ", action=" + json.action + ", data=" + json.responseData);

        var returnToURL = document.location;
        var objectId = json.objectId;
        var objectType = json.objectType;

        if (json.responseCode == this.RESPONSE_CODE_OK) {
            // there is an AddItem Request
            //todo: add Validation 

            if (json.action == undefined) {
                this.showError(this.PROCESSING_ERROR);
                return;
            }
	    this.showError(this.SUITCASE_ADD_MESSAGE); // not really an error, but display a message that we are forwarding to suitcase preview page
	    //TEMPORARY FIX FOR DISABLING EXITPOP WHEN GOING TO SUITCASE
	    this.disableExitPop();
	    var responseData = json.responseData;
	    if (window.opener) {
	    	    window.opener.queueSuitcaseSubmit(json.action, {"returnToURL": returnToURL, "addItemRequest": responseData, "objectId": objectId, "objectType": objectType});
			    window.opener.focus();
	    } else {
		this.createFormAndSubmit(json.action, 
			{"returnToURL": returnToURL, "addItemRequest": responseData, "objectId": objectId, "objectType": objectType});    
	    }
            
            return;

        } else if (json.responseCode == this.RESPONSE_CODE_ERROR_LOGIN) {
		 this.showError(this.NOT_LOGGED_IN_ERROR); // not really an error, but display a message that we are forwarding to suitcase preview page
            var addItemUrl = json.action; // we get the encoded URL with previous request data from the controller/json obj
	    if (window.opener) {
		// we are in a pop-up window
		 opener.window.location="/user/suitcase/login?returnto=" + escape(addItemUrl);
		 window.opener.focus();
	    } else {
		 window.location="/user/suitcase/login?returnto=" + escape(addItemUrl);	    
	    }
           
            return;

        } else if (json.responseCode == undefined || json.responseCode == this.RESPONSE_CODE_ERROR_GENERAL) {
            // catchall for cases where there is no errorcode, but no valid responseData either -- or there is a general error, thrown by an XML Generation exception
            this.showError(this.PROCESSING_ERROR);
	    //alert (json.responseCode);
            return;

        } else {
            this.handleException(json);
	    //alert (json.responseCode);
            return;
        }

    },

    createFormAndSubmit: function(formUrl, formDataObj) {
        var form = $(this.DYNAMIC_SUITCASE_FORM);

        if (form == undefined) {
            form = document.createElement("FORM");
            form.setAttribute("id", this.DYNAMIC_SUITCASE_FORM);
        }

        form.action = formUrl;
        form.method = 'post';

        for (prop in formDataObj) {
            var hiddenElem = document.createElement("input");
            hiddenElem.setAttribute("type", "hidden");
            hiddenElem.setAttribute("name", prop);
            hiddenElem.setAttribute("value", formDataObj[prop]);
            form.appendChild(hiddenElem);
        }  
	// if we are in a pop-up we should append to the parent, otherwise, just append to current doc
	document.body.appendChild(form);
	form.submit();
	
        
    },
    
    doSuitcaseSubmit: function(form) {
        document.body.appendChild(form);
	form.submit();
    },

    handleException: function(jsonResponse) {
        if (jsonResponse.responseCode == this.LOGIN_EXCEPTION_TYPE) {
            var loginUrl = jsonResponse.action;
            var returnToURL = document.location;

            if (loginUrl == undefined) { //should never happen
                this.showError(this.NO_ACTION_URL_ERROR);
                return;
            }

            this.createFormAndSubmit(loginUrl, {"returnToURL": returnToURL});
            return;

        } else if (jsonResponse.responseCode == this.OBJECTNOTFOUND_EXCEPTION_TYPE) {
            this.showError(this.OBJECTNOTFOUND_ERROR);
            return;

        } else { 
            this.showError(this.DEFAULT_ERROR);
            return;

        }
    }

};

function queueSuitcaseSubmit(formUrl, dataObj) {
	if (suitcaseControllerInstance == undefined) {
		suitcaseControllerInstance = new SuitcaseController();	
	}
	var formSubmitRef = suitcaseControllerInstance.createFormAndSubmit.bind(suitcaseControllerInstance);
	formSubmitRef(formUrl, dataObj);
	//window.setTimeout(formSubmitRef(formUrl, dataObj), 1);
}


