if( document.implementation.hasFeature("XPath", "3.0") )
{
	XMLDocument.prototype.selectNodes = function(cXPathString, xNode)
	{
		if( !xNode ) { xNode = this; } 

		var oNSResolver = this.createNSResolver(this.documentElement)
		var aItems = this.evaluate(cXPathString, xNode, oNSResolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
		var aResult = [];
		for( var i = 0; i < aItems.snapshotLength; i++)
		{
			aResult[i] =  aItems.snapshotItem(i);
		}
		
		return aResult;
	}
	XMLDocument.prototype.selectSingleNode = function(cXPathString, xNode)
	{
		if( !xNode ) { xNode = this; } 

		var xItems = this.selectNodes(cXPathString, xNode);
		if( xItems.length > 0 )
		{
			return xItems[0];
		}
		else
		{
			return null;
		}
	}

	Element.prototype.selectNodes = function(cXPathString)
	{
		if(this.ownerDocument.selectNodes)
		{
			return this.ownerDocument.selectNodes(cXPathString, this);
		}
		else{throw "For XML Elements Only";}
	}

	Element.prototype.selectSingleNode = function(cXPathString)
	{	
		if(this.ownerDocument.selectSingleNode)
		{
			return this.ownerDocument.selectSingleNode(cXPathString, this);
		}
		else{throw "For XML Elements Only";}
	}
}

function nodeInfo(t, v)
{
	this.text = t;
	this.voice = v;
}

function vvweb()
{
	
	this.doc = null;
	this.nodes = [];
	this.xmlhttp_array = [];
	this.flash = null;
	this.path = null;
	
	//default "reply error" handler (triggered when the server replies errors)
	this.error_handler = function(msg) {alert("ERROR: "+msg);};
	//default "flash not installed" handler (triggered when flash is not installed on the client)
	this.error_no_flash = function() {alert("ERROR: flash not installed");};
	//default "unable to find the flash movie" handler (triggered when javascript interacts with the flash movie)
	this.error_get_flash = function() {alert("ERROR: flash movie not found or not loaded");};
	//default "no html body" handler (triggered if the document does not have a body tag)
	this.error_no_body = function() {alert("ERROR: document body not found");};
	
	//debug
	this.notice_response = function (response) {alert("NOTICE: "+response);};
	
	this.init = function (path)
	{
		if (document.body)
		{
			this.flash= document.createElement('div');
			this.flash.id = "vvweb_frame";
			this.flash.style.width = "1px";
			document.body.appendChild(this.flash);
			this.path = path;
			var so = new SWFObject(path+"vvweb.swf", "vvweb_flash", "0", "0", "6", "#FF6600");
			if (so)
			{
				so.write("vvweb_frame");
			}
			else
			{
				this.error_no_flash();
			}
		}
		else
		{
			this.error_no_body();
		}
	}
	
	this.getFlashMovieObject = function (movieName)
	{
		if (window.document[movieName]) 
		{
			return window.document[movieName];
		}
		if (navigator.appName.indexOf("Microsoft Internet")==-1)
		{
			if (document.embeds && document.embeds[movieName])
		  		return document.embeds[movieName]; 
		}
		else // if (navigator.appName.indexOf("Microsoft Internet")!=-1)
		{
			return document.getElementById(movieName);
		}
	}
	
	this.play_mp3 = function (url)
	{
		var flashMovie=this.getFlashMovieObject("vvweb_flash");
		if (flashMovie)
		{
			flashMovie.GotoFrame(0);
			flashMovie.SetVariable("/:urls", url);
			flashMovie.GotoFrame(1);
		}
		else
		{
			this.error_get_flash();
		}
	}
	 
	/******************
	XMLHTTP
	******************/
	
	this.createRequestObject = function ()
	{
		var ro;
		var browser = navigator.appName;
		if(browser == "Microsoft Internet Explorer")
		{
			ro = new ActiveXObject("Microsoft.XMLHTTP");
		}
		else
		{
			ro = new XMLHttpRequest();
		}
		return ro;
	}
	
	this.get_xmlhttp = function ()
	{
		for (var i = 0; i < this.xmlhttp_array.length; i++)
		{
			if (this.xmlhttp_array[i].readyState == 4)
			{
				this.xmlhttp_array[i] = this.createRequestObject();
				return this.xmlhttp_array[i];
			}
		}
		var http = this.createRequestObject();
		this.xmlhttp_array.push(http);
		return http;
	}
	
	this.sndReq = function (action)
	{
		var http = this.get_xmlhttp();
		http.open('get', this.path+'vvweb.php?action='+action, true);
		http.onreadystatechange = function() {this.handleResponse(http);};
		http.send(null);
	}
	
	this.postReq = function (action, data)
	{
		var http = this.get_xmlhttp();
		http.open('POST', this.path+'vvweb.php?action='+action, true);
		http.onreadystatechange =function() { VVWEB.handleResponse(http);};
		//Send the proper header information along with the request
		http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		http.setRequestHeader("Charset", "utf-8");
		http.setRequestHeader("Content-length", data.length);
		http.setRequestHeader("Connection", "close");
		http.send(data);
	}
	
	this.handleResponse = function (http) 
	{
		var urls = [];
		if(http.readyState == 4)
		{
			var response = http.responseText;
			this.notice_response(response);
			
			if (response =='')
			{
				http=null;
				return;
			}
			
			var rxml = http.responseXML.documentElement;
			if (!rxml)
			{
				http=null;
				return;
			}
			
			var errors = rxml.getElementsByTagName('error');
			
			if (errors.length != 0)
			{
				for (var i = 0; i < errors.length; i++)
				{
					this.error_handler(errors[i].getAttribute('code') +": "+errors[i].getAttribute('message'));
				}
				return;
			}
			
			var responses = rxml.getElementsByTagName('message');
			if (!responses)
			{
				http=null;
				return;
			}
	
			for (var i = 0; i < responses.length; i++)
			{
				urls.push(responses[i].getAttribute('url'));
			}
			this.play_mp3(urls);
		}
	}
	
	this.load_nodes = function (root)
	{
		if (root)
		{
			for (var i =0; i < root.childNodes.length; i++)
			{
				if (root.childNodes[i].nodeType ==1)
				{
					if (root.childNodes[i].hasChildNodes())
					{
						if (root.getAttribute('speakable') == 'cascade')
						{
							root.childNodes[i].setAttribute('speakable', 'cascade');
							root.childNodes[i].setAttribute('voiceid', root.getAttribute('voiceid'));
						}
						this.load_nodes(root.childNodes[i]);
					}
				}
				else if (root.childNodes[i].nodeType ==3) //text node
				{
					if (root.getAttribute('speakable') == 'true' || root.getAttribute('speakable') == 'cascade')
					{
						this.nodes.push(new nodeInfo(root.childNodes[i].data, root.getAttribute('voiceid'))); //add node to array
					}
				}
			}
		}
	}
	
	this.parse_node = function (node)
	{
		var msgs = [];
		for (var i=0; i < node.childNodes.length; i++)
		{
			if (node.childNodes[i].nodeType == 3)
			{
				msgs.push(node.childNodes[i].data);
			}
		}
		return msgs;
	}
	
	this.speak = function ()
	{
		this.nodes = [];
		var xml = '<?xml version="1.0" encoding="utf-8"?><job>';
		this.load_nodes(document.body);
		for (var i = 0; i < this.nodes.length; i++)
		{
			if (this.nodes[i].text != "")
			{
				if (this.nodes[i].voice != 'undefined')
				{
					xml +='<message id="'+i+'" voice="'+this.nodes[i].voice+'">'+this.nodes[i].text+'</message>';
				}
				else
				{
					xml +='<message id="'+i+'">'+this.nodes[i].text+'</message>';
				}
			}
		}
		xml += '</job>';
		this.postReq('speak','xml='+xml);
	}
	
	this.stop = function()
	{
		var flashMovie=this.getFlashMovieObject("vvweb_flash");
		if (flashMovie)
		{
			flashMovie.GotoFrame(0);
		}
		else
		{
			this.error_get_flash();
		}
	}
}
var VVWEB = new vvweb();


