

function extend(subclass, superclass) {
  function Dummy(){}
  Dummy.prototype = superclass.prototype;
  subclass.prototype = new Dummy();
  subclass.prototype.constructor = subclass;
  subclass.superclass = superclass;
  subclass.superproto = superclass.prototype;
}

util.prototype.getBrowser= GetBrowser;
util.prototype.getOS= GetOS;
util.prototype.getBrowserVersion= GetBrowserVersion
//util constructor
function util ()
{}

function GetBrowser()
{
	var strBrowser = '';

	var strUA = navigator.userAgent.toLowerCase();

	if (_checkIt(strUA, 'konqueror'))
	{
		 strBrowser = "Konqueror";
	}
	else if  (_checkIt(strUA, 'chrome'))  strBrowser= "Google Chrome";
	else if  (_checkIt(strUA, 'safari'))  strBrowser= "Safari";
	else if  (_checkIt(strUA, 'opera'))   strBrowser= "Opera";
	else if  (_checkIt(strUA, 'msie'))    strBrowser= "Internet Explorer";
	else if (!_checkIt(strUA, 'compatible'))
	{
		strBrowser = "Netscape Navigator";
		//var strVersion = strDetect.charAt(8); // if required somewhere.
	}
	else strBrowser = "unknown";

	return strBrowser;
}

// Get OS
function GetOS()
{
    var strOS = '';

    var strUA = navigator.userAgent.toLowerCase();

    if (_checkIt(strUA, 'konqueror'))
    {
          strOS = "Linux";
    }

    if (!strOS)
    {
        if      (_checkIt(strUA, 'linux')) strOS = "Linux";
        else if (_checkIt(strUA, 'x11'))   strOS = "Unix";
        else if (_checkIt(strUA, 'mac'))   strOS = "Mac";
        else if (_checkIt(strUA, 'win'))   strOS = "Windows";
        else strOS = "unknown";
    }
    return strOS;
}

function GetBrowserVersion()
{
	if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent)) //test for Firefox/x.x or Firefox x.x (ignoring remaining digits);
		return new Number(RegExp.$1) // capture x.x portion and store as a number
	if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) //test for MSIE x.x;
		return new Number(RegExp.$1) // capture x.x portion and store as a number
	if (/Opera[\/\s](\d+\.\d+)/.test(navigator.userAgent)) //test for Opera/x.x or Opera x.x (ignoring remaining decimal places);
		return new Number(RegExp.$1) // capture x.x portion and store as a number
	if (/Safarie[\/\s](\d+\.\d+)/.test(navigator.userAgent)) //test for Opera/x.x or Safarie x.x (ignoring remaining decimal places);
		return new Number(RegExp.$1) // capture x.x portion and store as a number
}
	//helper function
function _checkIt(strUA, strKeyWord)
{
	return strUA.indexOf(strKeyWord) != -1;
}



function BSContactInstallLib()
{
	this.DetectedBrowser= this.getBrowser();
	this.DetectedBrowserversion=this.getBrowserVersion();
	this.OperatingSystem = this.getOS();
	this.BSVersion_MimeType = "application/x-bs-version-6";
	this.BSVersion_CLSID = "7C26EAE8-5ABF-495B-8956-49F35631CD11";
	this.BSVersionObject =null;
	this.BSSpecialBuild = "some-id";
	this.BSContactVersion = 0;
	this.BSContactSpecialBuild = 'no';
	this.BSContactBuildDate = 0;
	this.BSContactProductName = 'unknown';
	this.alreadyReadInformations = false;
	this.InstallerContainer = null;
	
//this function will detect contact if available
	this.BSContactAvailable = function()
	{
	  for(var C= 0; C<navigator.plugins.length; C++ )
	  {
		var Plug= navigator.plugins[C];

		if(   Plug.name.substring(0, 11) == 'BS Contact '
		   || Plug.name == 'BS Contact'
		  )
	return true;
	 }
	return false;
	}

	//-- detect the BS Version Plugin and return whether available or not
	this.Detect_BSVersion= function()
	{
	  if(this.DetectedBrowser == 'Internet Explorer')
	  {    
		var BSVersionObject= document.getElementById('BSVersion');
		
		if(BSVersionObject == undefined)
		{
			this.includeBSVersion()
		  return 'no';
		}

		if(BSVersionObject.Version == undefined)
		{
		  return 'no';
		 }

		 this.BSVersionObject = BSVersionObject;
		return 'yes';
	  }
	  else // the mozilla based versions
	  {
		navigator.plugins.refresh();
		if (navigator.mimeTypes && navigator.mimeTypes[this.BSVersion_MimeType]) 
		{
		  if (navigator.mimeTypes[this.BSVersion_MimeType].enabledPlugin && navigator.plugins && navigator.plugins["BS Version"]) 
		  {
			
				this.BSVersionObject= document.embeds['BSVersion'];
				if(this.BSVersionObject == undefined)
				{
				  this.includeBSVersion();
				  return 'no';
				}
			return 'yes';
		  }
		}
		return 'no';
	  }
	}
	
	this.includeBSVersion= function()
	{	
		
		if(this.DetectedBrowser == 'Internet Explorer')
		{
			this.InstallerContainer.innerHTML='<span Id= "BSVersionOuter"> <OBJECT id="BSVersion" name=BSVersion classid="clsid:'+this.BSVersion_CLSID+'" width=0 height=0 type=application/x-oleobject> </OBJECT></span>';
		}
		else
		{
			this.InstallerContainer.innerHTML='<span Id="BSVersionOuter"><embed Id=BSVersion name=BSVersion type="'+this.BSVersion_MimeType+'" width=0 height=0 ><\/span>';
		}	
	}
	
	//get the evaluated status of the BS Version
	this.ReadStatus = function ()
	{
		var status = 'cannot detect';
		
	  switch(this.Detect_BSVersion())
	  {
	  case 'no': // could not load the OCX or it's disabled in the browser.

		if(this.DetectedBrowser == 'Internet Explorer')
		{
			var BSVersionObject= document.getElementById('BSVersion');
			  if(''+ BSVersionObject.readyState == '4' || BSVersionObject.readyState == 'complete') // but only if it's not still loading.
			  {
				BSVersion_outer = document.getElementById('BSVersionOuter');
				var Code= BSVersion_outer.innerHTML;
				BSVersion_outer.innerHTML= '';
				BSVersion_outer.innerHTML= Code;
			  }
		}
		return 'not installed';
		break;
		
	  case 'yes':
		{
		  var rc= this.BSVersionObject.Update();
		  if(rc != 'ok')
		  {
			if(rc == 'not-installed')
			  status = 'not installed';  //BS Contact is not installed
			else if(rc == 'old-version')
			{			  
			  status = 'need update';		//an older version of BS Contact is installed before informations was available
			}else
			 status = 'cannot detect';	// detection of BS Contact failed, maybe it is installed, but an error occured
		  }else
		  {
			this.BSContactVersion = this.BSVersionObject.Version;
			this.BSContactSpecialBuild =this.BSVersionObject.SpecialBuild;
			this.BSContactBuildDate = this.BSVersionObject.BuildDate;
			this.BSContactProductName = this.BSVersionObject.ProductName;
			status = 'ok';
		  }
		  this.alreadyReadInformations = true;
		}
		break;
	  }
	  return status;
	}
	
	this.getVersion= function()
	{
		if(this.alreadyReadInformations)
		{
			return this.BSContactVersion;
		}
		else
		{
			this.ReadStatus();
			return this.BSContactVersion;
		}
	}
	
	this.getBuildDate= function()
	{
		if(this.alreadyReadInformations)
		{
			return this.BSContactBuildDate ;
		}
		else
		{
			this.ReadStatus();
			return this.BSContactBuildDate ;
		}
	}
	
	this.getProductName= function()
	{
		if(this.alreadyReadInformations)
		{
			return this.BSContactProductName;
		}
		else
		{
			this.ReadStatus();
			return this.BSContactProductName;
		}
	}
	
	this.getSpecialBuild= function()
	{
		if(this.alreadyReadInformations)
		{
			return this.BSContactSpecialBuild;
		}
		else
		{
			this.ReadStatus();
			return this.BSContactSpecialBuild;
		}
	}
	
	this.FreeUnusedLibraries = function()
	{
		this.BSVersionObject.FreeUnusedLibraries();
	}
	
	this.IsSpecialBuildId = function(specialBuildId)
	{
		return this.BSVersionObject.IsSpecialBuild(specialBuildId);
	}
	
	//ajax part for automatic retrieving the latest availabe version
	this.ajaxObject;
	this.ajaxRequestURL= "";
	this.BSContactAvailableVersion ="";
	AjaxSelf = this;
	
	this.getAjaxObject = function()
	{
		if (window.XMLHttpRequest)
		  {
		  // code for IE7+, Firefox, Chrome, Opera, Safari
		  this.ajaxObject = new XMLHttpRequest();
		  }
		if (window.ActiveXObject)
		  {
		  // code for IE6, IE5
		  this.ajaxObject = new ActiveXObject("Microsoft.XMLHTTP");
		  }
		  
		 if(this.ajaxObject)
		 {
			// add the callback handler
			this.ajaxObject.onreadystatechange = this.ajaxResponseCallback;
			//suggest the ajax url
			this.ajaxRequestURL= document.URL.substring(0,document.URL.lastIndexOf('/')+1);

			this.ajaxRequestURL+='ajaxResponse.php';
			AjaxSelf = this;
		 }
	}
	
	this.ajaxResponseCallback = function()
	{
		if (AjaxSelf.ajaxObject.readyState==4)
		{
			var xmlDoc=AjaxSelf.ajaxObject.responseXML.documentElement;
			AjaxSelf.BSContactAvailableVersion = xmlDoc.getElementsByTagName("Version")[0].childNodes[0].nodeValue;
			AjaxSelf.BSVersion_MimeType = xmlDoc.getElementsByTagName("Mime")[0].childNodes[0].nodeValue;
			AjaxSelf.BSVersion_CLSID = xmlDoc.getElementsByTagName("CLID")[0].childNodes[0].nodeValue;			
		}
	}
	
	this.SendAjax = function()
	{
		this.ajaxObject.open("GET",this.ajaxRequestURL,true); //don't do it asynchronously  // for vi: '
		this.ajaxObject.send(null);
	}
	
	this.useLatestAvailableVersion= function()
	{
		this.getAjaxObject();
		this.SendAjax();		
	}
	
}

extend(BSContactInstallLib,util);

function BSContactInstallerUI(InstallerContainer, EventHandler)
{
	//Interface paremeter

	this.requiredVersion = "";  //if requieredVersion is empty we assume to use the latest version
	this.availableVersion = ""; //this will override the internal CurrentAvailableVersion variable
	this.InstallerContainer = InstallerContainer; //this is a handle to the area where the installer information chould be inserted. It can be a element of type div, table cell or span
	this.internalProductName = "BS Contact VRML/X3D"; //the internal name of the product for identification
	this.specialBuildId = ""; // an identifier to select a build of BS Contact that was customized for you. You should have received the correct identifier from us via eMail. It's generally an id that names your company.  // for vi: '
	this.eventHandler= EventHandler;
	this.downloadUrlAdmin = "http://www.bitmanagement.com/download/BS_Contact/BS_Contact_Installer_IE7.exe";  // either this or .downloadUrl      is returned by .getDownloadUrl() .
	this.downloadUrl =      "http://www.bitmanagement.com/download/BS_Contact/BS_Contact_Installer.exe";      // either this or .downloadUrlAdmin is returned by .getDownloadUrl() .
	
	
	//internal variables --- don't change something here without knowing what you do----------------------------------------------------------------------------------------------------  // for vi: '
	this.BSContactInstallLibInstance = new BSContactInstallLib();
	this.needAjaxUpdate = false;
	this.prevStatus = '';
		
	this.prevText = "";
	
	this.prevVersionInfo;
	
	this.BSContactInstallLibInstance.InstallerContainer = this.InstallerContainer;
	this.BSContactInstallLibInstance.Detect_BSVersion();
	this.status = this.BSContactInstallLibInstance.ReadStatus();
	
	this.Timer;

	this.bFinished = false;

    this.bAlreadyNotifiedAboutPlatform= false;
	this.bAlreadyNotifiedAboutWrongPlatform= false;


	
	
	this.L = function(s)
	{
	  return s +'\n';
	}
		
	this.getVersionInfo= function()
	{
	    var Ret= {};
		
		Ret.installed= this.status == 'need update'?   'pre 7.2'                                     : 
		               this.status == 'not installed'? 'not installed'                               : 
					                                   this.BSContactInstallLibInstance.getVersion() ;
		
		Ret.required= this.requiredVersion;
		
		Ret.available= this.CurrentAvailableVersion;
		
	return Ret;
	}
	
	this.compareVersions= function(A, B)
	{
	  return    A.installed == B.installed
	         && A.required  == B.required
			 && A.available == B.available
			;
	}

	
	
	this.checkVersion = function()
	{
		//make an update
		this.status = this.BSContactInstallLibInstance.ReadStatus();
		if(this.status != 'ok')
	return;
	
		var res = false;
			
		if(this.BSContactInstallLibInstance.getSpecialBuild() == 'yes' && this.specialBuildId != "") //check if we have the correct special build version
		{
			res = this.BSContactInstallLibInstance.IsSpecialBuildId(this.specialBuildId);
		}
		else if(this.BSContactInstallLibInstance.getSpecialBuild() == 'no' && this.specialBuildId == "")
		{
			//we have no special build and it is not required
			//check if we have the right product installed e.g BS Contact Geo instead BS Contact
			if(this.internalProductName == "BS Contact VRML/X3D" && this.internalProductName != this.BSContactInstallLibInstance.getProductName()) //we need only BS Contact
				res= true;
			else if(this.internalProductName == this.BSContactInstallLibInstance.getProductName())
				res = true;
			else //we need a special version of BS Contact
			{
				this.status= 'not installed';
	return;
			}
		}
		else//otherwise we have no special build but a special build is required, so we leave res to false and exit imidiently
		{
			this.status= 'not installed';
    return;
		}
		
		
		if(res)
		{
			if(this.requiredVersion != "") //the customer whats to check against a special version
			{
				//check if required version is lower or equal to available version
				if(Math.floor(parseFloat(this.CurrentAvailableVersion) * 1000) >= Math.floor(parseFloat(this.requiredVersion)* 1000))
					res = Math.floor(parseFloat(this.BSContactInstallLibInstance.getVersion()) * 1000) >= Math.floor(parseFloat(this.requiredVersion)* 1000);
				else //check against the available version
					res = Math.floor(parseFloat(this.BSContactInstallLibInstance.getVersion()) * 1000) >= Math.floor(parseFloat(this.CurrentAvailableVersion)* 1000);
			}
			else //we have to check against the latest avaialable version
			{
				res = Math.floor(parseFloat(this.BSContactInstallLibInstance.getVersion()) * 1000) >= Math.floor(parseFloat(this.CurrentAvailableVersion)* 1000);
			}
		}

		this.status= res? 'ok' : 'need update';
	}


	
	this.ShowInstallHelp=function()
	{
		var InstallHelp=document.getElementById("InstallHelp");
		if(InstallHelp)
		{
			var Install=document.getElementById("install");
			if(Install)
			{
				var ClassID = Install.className; //getAttribute("className",0);
				if(ClassID == 'install')
				{
					Install.className = 'installExpanded';
					InstallHelp.style.visibility="visible";
				}
				else
				{
					Install.className = 'install';
					InstallHelp.style.visibility="hidden";
				}
			}
		}
	}

	// To retreive the default download URL.
	
	this.getDownloadUrl= function()
	{
		if(this.BSContactInstallLibInstance.DetectedBrowser== 'Internet Explorer' && parseFloat(this.BSContactInstallLibInstance.DetectedBrowserVersion)*10 < 80)
	return this.downloadUrlAdmin;
		else
	return this.downloadUrl;
	}	

	

	
	// Should be called before we open the content.
	this.StopRunning= function()
	{
//	  clearTimeout(this.Timer);
//	  this.bFinished= true;

	  if(this.BSContactInstallLibInstance.Detect_BSVersion() == 'yes')
		this.BSContactInstallLibInstance.FreeUnusedLibraries();
	}

	this.Run= function()
	{
		if(this.bFinished)
			return;
		
//		var Out ='';

		if(!this.bAlreadyNotifiedAboutPlatform)
		{
			this.bAlreadyNotifiedAboutPlatform= true;
			this.eventHandler({what: 'platform detected', platform: this.BSContactInstallLibInstance.OperatingSystem});
		}
		
		if(this.BSContactInstallLibInstance.OperatingSystem != 'Windows')
		{
			//this.bFinished= true;

			if(!this.bAlreadyNotifiedAboutWrongPlatform)
			{
				this.bAlreadyNotifiedAboutWrongPlatform= true;
				this.eventHandler({what: 'platform not supported', platform: this.BSContactInstallLibInstance.OperatingSystem});
			}
	return;
		}
		
		if(this.availableVersion == "" && this.specialBuildId == "" && this.BSContactInstallLibInstance.BSContactAvailableVersion == "") //we have to check the latest version on our server
		{
			this.BSContactInstallLibInstance.useLatestAvailableVersion();
			this.needAjaxUpdate = true;		
		}
		else if(this.availableVersion != "")
			this.CurrentAvailableVersion = this.availableVersion;
		
		if(this.needAjaxUpdate)
		{
			if(this.BSContactInstallLibInstance.BSContactAvailableVersion != "")
			{
				this.CurrentAvailableVersion = this.BSContactInstallLibInstance.BSContactAvailableVersion;
				this.needAjaxUpdate=false;
				//clearTimeout(this.Timer);			// TBD: Why do we stop querying here?
			}
			else
			{
				this.scheduleRun(100);
				return;
			}
		}
		
		this.checkVersion();

		var versionInfo= this.getVersionInfo();
		
	    if(   this.status != this.prevStatus
		   || this.compareVersions(versionInfo, this.prevVersionInfo) != true
		  )
		{
			var whatHasChanged= this.status != this.prevStatus? 'status' : 'version';
		
			this.prevStatus= this.status;
			this.prevVersionInfo= versionInfo;
			
			this.eventHandler( { what: whatHasChanged +' changed'
							   , status: this.status
							   , canProceed: this.status == 'ok'
							   , version: versionInfo
							   }
							 );
		}
		
		
		if(!this.bFinished) 
		{
			this.scheduleRun(300);
		}
	}
	
	this.scheduleRun= function(HowLong)
	{
		this.Timer= setTimeout(( function(obj){ return function(){ obj.Run(); } } )(this), HowLong);
	}
}



