///<reference path="../TESCO.js" />
///<reference path="event.js" />
///<reference path="event.manager.js" />

/*
	Example: 
	
	throw new TESCO.system.Exception("TESCO.$: parameter 'namespace' must be defined");
*/
TESCO.system.Exception = (function() {

	function _constructor(message, ary, functionName, dialogue) {
		/// <summary>thrown exceptions</summary>
		/// <param name="message">string</param>
		/// <param name="ary">string</param>
		/// <param name="functionName">string</param>
		/// <param name="dialogue">object</param>
		/// <returns>instance</returns>
	    this.message = message;
	    this.functionName = (functionName ? ary + "." + functionName : ary);
	    this.dialogue = dialogue || TESCO.UI.Dialogue.Error;
	    return this;
    }
    _constructor.prototype.NAME = "TESCO.system.Exception";

	_constructor.prototype.toString = function() {
		return this.functionName + ": " + this.message;
	}
	
	return _constructor;
})();

/*
	Example: 
	
	TESCO.system.Exception.handler.raise(new TESCO.system.Exception("Zero increment in meta-data - product " + f.id, "entities.js"));
*/
TESCO.system.Exception.handler = new function() {
	// Call raise, passing an exception to log an error
	this.NAME = "TESCO.system.Exception.handler";
	
	TESCO.system.event.manager.call(this, "exceptionRaised");
	
	var _self = this;
	
	this.raise = function(e) {
		/// <summary>raise an exception, without throwing</summary>
		var exceptionStr = "TESCO.system.Exception: \""  + e.message + "\"\n" + (e.fileName ? "In file \"" + e.fileName + "\"" : "") + (e.lineNumber ? " at line \"" + e.lineNumber + "\"" : "");
		if (TESCO.sites.Configuration.application.debug) {
		    console.log(exceptionStr);
		}
		
		//  dispatch tesco exception
        _self.dispatchEvent("exceptionRaised", exceptionStr);
    }
}

//  define different behaviours for different status codes
TESCO.system.Exception.InvalidStatus = (function() {
    
    //  private static
    var _status = {
	    found : 302
    }
    
    function _authenticationError(url) {
        return (url.indexOf(TESCO.sites.Configuration.application.domain.secure) > -1);
    } 

    function _constructor(ary, functionName, request) {
		/// <summary>invalid status response (not 200). derived from TESCO.system.Exception</summary>
		/// <param name="ary">string</param>
		/// <param name="functionName">string</param>
		/// <param name="request">object</param>
		/// <returns>instance</returns>
        var _message;
        var _dialogue = null;
        switch (request.status) {
            case _status.found : 
                var _url = request.getResponseHeader("Location");
                if (_authenticationError(_url)) {
                    _dialogue = TESCO.UI.Dialogue.AuthenticationError;
                    this.location = _url;
                    _message = TESCO.locale.exception.authenticationError;
                    //  only break if _authenticationError(_url), otherwise default
                    break;
                }
            default : 
                _message = TESCO.locale.exception.invalidStatus.format(request.status, request.statusText);
        }

        _constructor.base.constructor.call(this, _message, ary, functionName, _dialogue)
        return this;
    }
    _constructor.extend(TESCO.system.Exception);
    
    //  default instance attributes
    _constructor.prototype.NAME = "TESCO.system.Exception.InvalidStatus";
    
    return _constructor;
})();