// Request Manager v3.0
// Copyright (c) Alexander Shpack, 2009-now().

var RM = function() {

	// Fields

	var stack = new stackManager();
	var ajaxCounter = 0;
	var jsCounters = [];
	var proxyContainer = null;

	// Private methods

	var createProxyContainer = function ( ) {
		try {
			var bodyNode = $$("BODY").item(0);

			var container = $("RM_proxyContainer");
			if ( container ) return;

			var container = document.createElement( "DIV" );
			bodyNode.appendChild( container );

			container.id = "RM_proxyContainer";

			proxyContainer = container;

		} catch ( e ) { }
	};

	var createProxyFrame = function ( package ) {
		try {
			var id = package.pID;
			var frameExist = true;

			var tmpNode = $( id + "_proxyFrameID" );

			if ( !tmpNode ) {
				frameExist = false;
				try {
					tmpNode = document.createElement( "<iframe class='proxyFrame' id='" + id + "_proxyFrameID' name='" + id + "_proxyFrame'><\/iframe>" );
				} catch( e ) {
					tmpNode = document.createElement( "IFRAME" );
					$setAttributes ( tmpNode, { className: "proxyFrame", id: id + "_proxyFrameID", name: id + "_proxyFrame", src: "about:blank" } );
				};

				proxyContainer.appendChild( tmpNode );
			}

			package.proxyFrame = tmpNode;

			return frameExist;

		} catch ( e ) { };
	};

	var createProxyForm = function ( package ) {
		try {

			var id = package.pID;

			var formNode = $( id + "_proxyForm" );

			if ( !formNode ) {
				var formNode = document.createElement( "FORM" );
				setProxyFormAttr ( formNode, package );
				proxyContainer.appendChild( formNode );
			} 
			else
			{
				$clearNodeContent( formNode );
			}
		
			createProxyFormElements ( formNode, package );

			package.proxyForm = formNode;

		} catch ( e ) { }
	};
	var setProxyFormAttr = function ( formNode, package ) {
		try {
			var id = package.pID;
		    with ( package.options ) {
				formAttr.target = id + "_proxyFrame";
				formAttr.action = formAttr.action || "/";
				formAttr.method = ( formAttr.method != undefined )? formAttr.method : (window.develMode)?  "GET" : "POST";
				formAttr.id = id + "_proxyForm";
				formAttr.className = "proxyForm";

				if ( formAttr.enctype && window.IE ) formAttr.encoding = formAttr.enctype;
	 
				$setAttributes ( formNode, formAttr );
			};
		} catch ( e ) { }
	};
	var createProxyFormElements = function ( formNode, package ) {
		try {
			with( package.options) {
				for ( var i in data ) {
					if ( data[ i ].nodeName && data[ i ].nodeName == "INPUT" && data[ i ].type == "file" ) {
						cloneInputFile( formNode, data[ i ], i );
					}
					else
					{
						var tmpNode = document.createElement( "INPUT" );
						$setAttributes ( tmpNode, { type: "hidden", value: data[ i ], name: i } );
						formNode.appendChild( tmpNode );
					}
				}
			}
		} catch ( e ) { }
	};
	var cloneInputFile = function ( formNode, inputFile, elName ) {
		try {
			var inputClone = inputFile.cloneNode( true );
			inputFile.parentNode.insertBefore( inputClone, inputFile );
			inputFile.name = elName;
			inputFile.id = "";
			formNode.appendChild( inputFile );

		} catch ( e ) { return false };
	};

	var clearPackage = function ( index ) {
		try {

			var package = stack.get( index ).obj;
			if ( package.proxyFrame ){
				proxyContainer.removeChild( package.proxyFrame );
			};
			if ( package.proxyForm ){
				proxyContainer.removeChild( package.proxyForm );
			};
			stack.remove( index, true );

		} catch ( e ) { return false }
	};

	var proxyLoadHandler = function ( package, index ) {
		try {

			var frameNode = package.proxyFrame;
			var frameDoc = frameNode.contentWindow.document;

			if( frameDoc.location == "about:blank" ) return; // Opera magic

			var htmlNode = frameDoc.getElementById( "htmlContainer" );
			var jsNode = frameDoc.getElementById( "jsContainer" );

			if ( htmlNode ) {
				if ( document.importNode ) htmlNode = document.importNode( htmlNode, true );
				$moveNodeContent ( htmlNode, package.id );

			}

			if ( jsNode ) {
	   	
				if ( document.importNode ) jsNode = document.importNode( jsNode, true );

				if ( window.execScript && jsNode.innerText != "" ) {
					window.execScript ( jsNode.innerText );
				}
				else 
				{
					var tmpScriptNode = document.createElement ( "SCRIPT" );
					tmpScriptNode.type = "text/javascript";
					$moveNodeContent ( jsNode, tmpScriptNode );
					var container = $(package.id);
					container.appendChild( tmpScriptNode );
				}
			}

			if ( package.options.onLoadHandler ) {
				package.options.onLoadHandler( package );
			};

			setTimeout( function() { clearPackage( index ) }, 10 );

		} catch ( e ) {};
	};

	var showLoading = function ( id ) {
		try {
			$clearNodeContent( id );
			var targetNode = $( id );

	    	var tplNode = $( "loadingTpl" );
    	    var cloneNode = tplNode.cloneNode( true );
	        cloneNode.id = "";
	        targetNode.appendChild( cloneNode );

		} catch ( e ) {};
	};

	var isDoubleClick = function ( package ) {
		try {
			var storedPackage = stack.get( package.proxyFrame.stackIndex );
			if ( package.timeStamp - storedPackage.obj.timeStamp > 1000 ) return false;
			return true;
		} catch ( e ) { return false };
	};


    // Public Methods

    var init = function ( ) {
		try {
			createProxyContainer();
		} catch ( e ) { }
    };

	var makeDataRequest = function ( id, options ) {
		try {

			var self = this;
			this.onBeforeRequest ( id, options );

			showLoading( id );

			var containerNode = $( id );
			if ( !containerNode || !options ) return;

			var package = { id: id, options: options||{}, proxyForm: null, onLoad: proxyLoadHandler, timeStamp: new Date() };

			package.pID = options.cID || id;

			var frameExist = createProxyFrame( package );

			if ( options.url ) {

				package.proxyFrame.src = options.url;	
	
			}
			else
			{
				if ( frameExist && isDoubleClick( package ) ) return;

				if ( !options.formAttr ) package.options.formAttr = {};
				if ( !options.data ) package.options.data = {};

				createProxyForm ( package );
				
				package.proxyForm.submit();
			
			}; 

			if ( !frameExist ) {
				var index = stack.add( package );
				package.proxyFrame.stackIndex = index;
				$addEventListener( package.proxyFrame, "load", function(){ proxyLoadHandler( package, index ) } );
			};

			this.onAfterRequest ( package, index );

		} catch ( e ){ };
	};
	var makeDataRequestOnce = function ( id, options ) {
		try {
			var node = $(id);
			if ( node.innerHTML == "" ) { this.makeDataRequest( id, options ) }
		} catch ( e ){ };
	};


	var makeAJAXRequest = function ( options, handler ) {
		try {
			var requestObj = null;
			requestObj = new XMLHttpRequest();
		} catch ( e ) { 
			try { 
				requestObj = new ActiveXObject( "Msxml2.XMLHTTP" );
			} catch ( e ) { return false };
		};

		try {

			var method = options.method || "GET";
			requestObj.open( method, options.uri, true );
    
			var sendData = options.sendData || null;
			requestObj.send( sendData );
		
		    requestObj.responseType = options.responseType || "XML";
			requestObj.handler = handler || function() {};

			ajaxCounter++;
    
			requestObj.onreadystatechange = function () {
				try {
					if ( this.readyState == 4 && this.status == 200 ) {
						var response = ( this.responseType == "XML" )? this.responseXML : this.responseText;
						this.handler( response, ajaxCounter );
					};
				} catch ( e ) { return false }
			};

			return ajaxCounter;

		} catch ( e ) { return false };
	};

	var makeJSRequest = function ( requestID, options ) {
		try {
	 		var headNode = $$('HEAD').item(0);
 			var scriptNode = $( "jsProxy_" + requestID );

 			if ( scriptNode ) { $delNode( scriptNode ) };

	 		scriptNode = document.createElement("SCRIPT");
 			headNode.appendChild( scriptNode );

 			scriptNode.setAttribute( "type", "text/javascript" )
	 		scriptNode.id = "jsProxy_" + requestID;
 			scriptNode.src = $objAsURI( options );

 			if ( !jsCounters[ requestID ] ) { jsCounters[ requestID ] = 0 };
 			jsCounters[ requestID ]++;
 			return jsCounters[ requestID ];

		} catch ( e ) { return false };
	};

    // Handlers

	var onBeforeRequest = function ( ) {};
	var onAfterRequest = function ( ) {};

	return {
	 
		// Public Methods
		init: init
		,makeDataRequest: makeDataRequest
		,makeDataRequestOnce: makeDataRequestOnce
		,makeAJAXRequest: makeAJAXRequest
		,makeJSRequest: makeJSRequest

		// Public Handlers
		,onBeforeRequest: onBeforeRequest
		,onAfterRequest: onAfterRequest

	}

}();

//RM.init();
