/**
 * Beskrivelse
 * 
 * @author	Thomas Sømoen <thomas at apt.no>
 * @version	20061005
 * @package	net
 */
var net = new Object();
net.READY_STATE_UNINITIALIZED=0;
net.READY_STATE_LOADING=1;
net.READY_STATE_LOADED=2;
net.READY_STATE_INTERACTIVE=3;
net.READY_STATE_COMPLETE=4;

/**
 * Klasse om håndterer forespørsler mellom klient og tjener.
 * 
 * @access	public
 * @author	Tommy Gildseth  <tommy at apt.no>
 * @author	Thomas Sømoen <thomas at apt.no>
 * @version	20061005
 * @package	net
 */
net.XmlHttp = function(url, observer) {
	//member variables
	this.request		= null;
	this.isIE			= false;
	this.response		= null;
	this.observer		= new Array();
	this.method			= 'GET';
	this.params			= new Array();
	this.load(url);
}

/**
 * Definerer objektets metoder.
 * 
 * @since	20061005
 */
net.XmlHttp.prototype = {
	/**
	 * Legger til parameter som skal sendes til tjener.
	 * 
	 * @access	public
	 * @since	20061005
	 * @param	string	name	Parameternavn
	 * @param	string	value	Parameterverdi
	 */
	reqParam:function(name, value){
		this.params.push(escape(name) + "=" + escape(value));
	},
	
	/**
	 * Setter forespørselsmetoden.
	 * 
	 * @access	public
	 * @since	20061005
	 * @param	string	method	Typen forespørsel som skal gjøres. kan være GET eller POST
	 */
	requestMethod:function( method ) {
		if (method == 'GET' || method == 'POST') {
			this.method = method;
		} else {
			throw('Invalid request method');
		}
	},
	
	/**
	 * Setter objektet som overvåker forespørselen.
	 * 
	 * @access	public
	 * @since	20061005
	 * @param	Object	observer	Objektet som overvåker forespørslen.
	 */
	attach:function( observer ) {
		this.observer.push(observer);
	},
	
	/**
	 * Funksjonen laster filen fra tjeneren.
	 * 
	 * @access	public
	 * @since	20061005
	 * @param	string	url	Filen som skal lastes fra tjeneren.
	 */
	load:function( url ) {
		try {
	        if (url) {
	            this.loadXMLDoc(url);
	        }
	    }
	    catch(e) {
	        var msg = (typeof e == "string") ? e : ((e.message) ? e.message : "Ukjent feil");
	        alert("Feil i AJAX kall til tjener:\n" + msg);
	        return;
	    }
	},
	
	/**
	 * Funksjonen oppretter XmlHttp objektet og gjøre forespørselen til tjeneren.
	 * 
	 * Det tas hensyn til metodeulikhetene på kryss av nettleserne.
	 * 
	 * @access	public
	 * @since	20061005
	 * @param	string	url	Filen som skal lastes fra tjeneren.
	 */
	loadXMLDoc:function(url) {
		objXmlHttp 	= this;
	  	reqParams 	= this.params.join('&');
	  	if( this.method == 'GET') {
	    	url = url + "?" + reqParams;
	  	}
	
	    // branch for native XMLHttpRequest object
	    if( window.XMLHttpRequest ){
	        this.req = new XMLHttpRequest();
	    // branch for IE/Windows ActiveX version
	    } else if ( window.ActiveXObject ) {
	        this.isIE 	= true;
	       	this.req 	= new ActiveXObject("Microsoft.XMLHTTP");
	    }
	
	    if( this.req ){
	      this.req.onreadystatechange = function ( ) { objXmlHttp.processChange(); }
	      this.req.open(this.method, url, true);
	      if (this.method == 'POST') {
	        this.req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
	      }
	      this.req.send(reqParams);
	    }
	},
	
	/**
	 * Funksjon som overvåker svaret fra tjeneren.
	 * 
	 * Funsksjonen svarer når tjeneren har sendt ferdig. Den sjekker så svarets innholdtype og oppretter et javascript-objekt dersom innholdtypen er json, rent tekst dersom det er tekst eller html, og et DOM-tre dersom det er XML.
	 * Dersom det skjer en feil kalles feilhåndterrer eller standard feilfunksjon.
	 * 
	 * @access	public
	 * @since	20061005
	 */
	processChange:function() {
	    // only if req shows "loaded"
	    if (this.req.readyState == net.READY_STATE_COMPLETE) {
	        // only if "OK"
	        if (this.req.status == 200) {
				var response = null;
				var contentType = this.req.getResponseHeader("Content-type").split(';');
				switch(contentType[0]){
					case 'text/json':
						this.response = eval("("+ this.req.responseText+")");
						break;
					case 'text/xml':
						this.response = this.req.responseXML;
						break;
					default:
						this.response = this.req.responseText;
				}
				
				for(i = 0; i < this.observer.length; ++i) {
					this.observer[i].notify(this.response);
				}
	         } else {
	            alert("Det oppsto et problem under kommunikasjon med tjener:\n" +
	                this.req.statusText);
	         }
	    }
	}
}

/**
 * Klasse som håndterer objektet som skal varsles når tjeneren har sendt svaret sitt.
 * 
 * @access	public
 * @author	Tommy Gildseth  <tommy at apt.no>
 * @author	Thomas Sømoen <thomas at apt.no>
 * @version	20061005
 * @package	net
 */
net.Observer = function() {
	this.target = null;
}

/**
 * Funksjon som kalles når tjeneren har send ferdig. Funksjonen er her satt til en defaultfunksjon som viser en alert-boks med svaret.
 * 
 * @access	public
 * @since	20061005
 * @param	var	response	Svaret fra tjeneren
 */
net.Observer.prototype.onLoad = function(response){
	alert(response);
}

/**
 * Funksjon som kalles når det oppstår en feil. Funksjonen er her satt til en defaultfunksjon som viser en alert-boks med feilmelding.
 * 
 * @access	public
 * @since	20061005
 * @param	var	response	Svaret fra tjeneren
 */
net.Observer.prototype.onError = function(message){
	alert(message);
}

/**
 * Kort
 * 
 * @access	public/private/protected
 * @since	### (versjonsnummer eller dato(YYYYMMDD))
 * @param	type	variabel	Beskrivelse
 * @return	type	Beskrivelse
 * @see	classname::function()
 */
net.getElementTextNS = function(prefix, local, parentElem, index) {
    var result = "";
    if (prefix && isIE) {
        // IE/Windows way of handling namespaces
        result = parentElem.getElementsByTagName(prefix + ":" + local)[index];
    } else {
        // the namespace versions of this method
        // (getElementsByTagNameNS()) operate
        // differently in Safari and Mozilla, but both
        // return value with just local name, provided
        // there aren't conflicts with non-namespace element
        // names
        result = parentElem.getElementsByTagName(local)[index];
    }
    if (result) {
        // get text, accounting for possible
        // whitespace (carriage return) text nodes
        if (result.childNodes.length > 1) {
            return result.childNodes[1].nodeValue;
        } else if (result.firstChild) {
            return result.firstChild.nodeValue;
        } else {
			return '';
		}
    } else {
        return "n/a";
    }
}
