/**
	Description: This class works with uTorrent WebUI.
	Links:
		http://www.utorrent.com/intl/ru/developers/webapi
		http://techss.net/docs/uTorrent_Server.html
	Author: Drachenko Viktor
*/
var uTrnt = new function uTorrent() {
	this.url = ""; // @see variables.js
	this.token = '';
	this.iframeId = 'uTorrentIFrameId';
	this.iframe;
	this.urlTorrent = ""; // @see variables.js
	this.hashTorrent;
	this.filesTorrent = [];
	this.filesTorrentSize = [];
	this.execQueue = [];
	this.binTorrentPath = "tools\\utorrent\\uTorrent.exe";
	this.binTorrentPathDefault = '';
	this.binTorrentParams = " /recover /hide ";
	this.binTorrentRunned = false;
	this.binTorrentScript = null;
	this.downloadDir = 'download';
	this.tempDir = 'DRPSu_TEMP';
	this.status = {};
	this.torrentSettings = {
			dir_active_download: '',
			dir_active_download_flag: 1,
			dir_torrent_files: '',
			dir_torrent_files_flag: 1,
			dir_completed_download: '',
			dir_completed_download_flag: 0,
			dir_completed_torrents_flag: 0,
			torrents_start_stopped: 1,
			close_to_tray: 0,
			minimize_to_tray: 0,
			tray_activate: 0,
			'tray.show': 0
	};
	this.updateStatusTimer = null;
	this.checkTorrentPidTimer = null;
	this.logAll = '';
	this.logAllIndex = 0;
	this.log = function(name){
		if ( this.logAllIndex > 1000 ) {
			this.logAllIndex = 0;
			this.logAll = '';
		}
		this.logAll += (++this.logAllIndex)+': '+name+"\n";
		//alert(this.logAll);
	};
	this.onUpdateStatus = function(status) {
		var tr = this;
		downloadProgressBar(status['progress'],status);
		if ( status['progress'] == 100 ) {
			tr.moveDownloadedFiles('drp','drp');
			tr.moveDownloadedFiles('dev_db','dev_db');
			window.close();
		}
	};
	// Initialization
	this.init = function() {
		this.log('init');
		var tr = this;
		this.url = torrentWebUiUrl;
		this.urlTorrent = torrentFileUrl;
		if ( this.updateStatusTimer )
			clearInterval(this.updateStatusTimer);
		if ( this.checkTorrentPidTimer )
			clearInterval(this.checkTorrentPidTimer);
		// Sets temp dir
		var WshShell = new ActiveXObject("WScript.Shell");
		this.tempDir = this.getEnv('TEMP')+'\\DRPSu_TEMP';
		// Sets download dir
		this.downloadDir = this.tempDir+'.download';
		// Invokes queue
		tr.initSettings();
		tr.execQueue.push('addTorrent();');
		tr.execQueue.push('skipAllFiles();');
		tr.execQueue.push('stopTorrent();');
		tr.runTorrent();
	};
	// Initialization of settings
	this.initSettings = function() {
		this.log('initSettings');
		var tr = this;
		this.torrentSettings['dir_active_download'] = this.downloadDir;
		this.torrentSettings['dir_torrent_files'] = this.downloadDir;
		this.torrentSettings['dir_completed_download'] = this.downloadDir;
		this.execQueue.push('setSettings('+this.dumpObject(this.torrentSettings)+');');
	};
	// Executes next call in queue
	this.callQueueNext = function() {
		this.log('callQueueNext');
		var tr = this;
		if ( this.execQueue.length > 0 ) {
			var nextCall = 'tr.'+this.execQueue.shift();
			try {
				eval(nextCall);
			} catch(e){};
		}
	}
	// Moves downloaded file to dir
	this.moveDownloadedFiles = function(fromFolderName,toFolderName) {
		this.log('moveDownloadedFiles');
		var fromFolderNamePrefix = this.downloadDir+'\\'+this.status.name;
		fromFolderName = typeof fromFolderName === 'string'
			? fromFolderName = fromFolderNamePrefix+'\\'+fromFolderName
			: fromFolderName = fromFolderNamePrefix;
		fsMergeFolders(fromFolderName,toFolderName);
	};
	// Runs uTorrent.exe
	this.runTorrent = function() {
		this.log('runTorrent');
		var tr = this;
		if ( ! this.binTorrentRunned ) {
			this.binTorrentRunned = true;
			var WshShell = new ActiveXObject("WScript.Shell");

			this.binTorrentPathDefault = WshShell.RegRead('HKCU\\Software\\Classes\\uTorrent\\shell\\open\\command\\');
			if ( !this.binTorrentPathDefault )
				this.binTorrentPathDefault = WshShell.RegRead('HKLM\\Software\\Classes\\uTorrent\\shell\\open\\command\\');
			this.binTorrentPathDefault = this.binTorrentPathDefault.replace(/"|\%.*$/g,'').replace(/ +$/,'');
			if ( this.binTorrentPathDefault.length && !fsFileExists(this.binTorrentPathDefault) )
				this.binTorrentPathDefault = '';
			// Runs user torrent
			if ( this.binTorrentPathDefault.length ) {
				
				var binTorrentName = this.binTorrentPathDefault.substring(this.binTorrentPathDefault.lastIndexOf('\\')+1);
				var userAppConfFile = this.getEnv('APPDATA')+'\\uTorrent\\settings.dat';
				var userDefConfFile = this.binTorrentPathDefault.substring(0,this.binTorrentPathDefault.lastIndexOf('\\'))+'\\settings.dat';
				var trntConfFile = this.binTorrentPath.substring(0,this.binTorrentPath.lastIndexOf('\\'))+'\\settings.dat';
				
				// Makes copies of settings.dat
				if ( fsFileExists(userDefConfFile) ) {
					if ( fsCopyFile(userDefConfFile,userDefConfFile+'.back') && fsCopyFile(trntConfFile,userDefConfFile) ) {
						// Runs user torrent.exe
						this.killTask(binTorrentName);
						this.binTorrentScript = WshShell.Exec(this.binTorrentPathDefault+' /MINIMIZED');
					} else {
						this.binTorrentPathDefault = '';
					}
				} else {
					if ( fsCopyFile(userAppConfFile,userAppConfFile+'.back') && fsCopyFile(trntConfFile,userAppConfFile) ) {
						// Runs user torrent.exe
						this.killTask(binTorrentName);
						this.binTorrentScript = WshShell.Exec(this.binTorrentPathDefault+' /MINIMIZED');
					} else {
						this.binTorrentPathDefault = '';
					}
				}
				
				
			}
			// Runs self torrent
			if ( ! this.binTorrentPathDefault.length ) {
			
				var torrentDir = this.binTorrentPath.substring(0,this.binTorrentPath.lastIndexOf('\\'));
				var binTorrentPath = this.tempDir+'\\'+this.binTorrentPath.substring(this.binTorrentPath.lastIndexOf('\\')+1);
				
				if ( fsCopyFolder(torrentDir,this.tempDir) ) {
					this.binTorrentScript = WshShell.Exec(binTorrentPath+' '+this.binTorrentParams);
				} else {
					alert('ERROR: Can\'t copy utorrent.exe into temp directory.');
					window.close();
				}
				
			}
			// Checking torrent.exe runned.
			if ( this.checkTorrentPidTimer )
				clearInterval(this.checkTorrentPidTimer);
			this.checkTorrentPidTimer = setInterval(function() {
				if ( typeof tr.binTorrentScript == 'object' && tr.binTorrentScript.ProcessID ) {
					tr.binTorrentRunned = tr.checkPID( tr.binTorrentScript.ProcessID );
					if ( ! tr.binTorrentRunned ) {
						clearInterval(tr.checkTorrentPidTimer);
						alert('uTorrent.exe был неожиданно завершен!\n\nЗапустите конструктор заново.');
						window.close();
					}
				}
			},1000);
		}
		setTimeout(function(){
			//tr._detectTokenTorrent();
			tr.callQueueNext();
		}, 500);
	};
	// Kills torrent.exe
	this.killTorrent = function() {
		this.log('killTorrent');
		var tr = this;
		if ( tr.binTorrentRunned ) {
			if ( ! tr.binTorrentPathDefault.length ) {
				tr.delTorrent();
			} else {
				if ( confirm("Оставить раздачу закаченных драйверов для других пользователей?") )
					tr.startTorrent();
				else				
					tr.delTorrent();
			}
			tr.sleep(0);
			if ( tr.updateStatusTimer )
				clearInterval(tr.updateStatusTimer);
			try {
				tr.binTorrentScript.Terminate();
			} catch(e) {}
			fsDelete(this.tempDir);
			tr.binTorrentRunned = false;
		}
		//tr.sleep(1);
		if ( tr.binTorrentPathDefault.length ) {
			var WshShell = new ActiveXObject("WScript.Shell");
			var userAppConfFile = this.getEnv('APPDATA')+'\\uTorrent\\settings.dat';
			var userDefConfFile = this.binTorrentPathDefault.substring(0,this.binTorrentPathDefault.lastIndexOf('\\'))+'\\settings.dat';
			// Reverts copies of settings.dat
			if ( fsFileExists(userDefConfFile) ) {
				if ( fsCopyFile(userDefConfFile+'.back',userDefConfFile) ) {
					// Runs user torrent.exe
					this.binTorrentScript = WshShell.Exec(this.binTorrentPathDefault+' /MINIMIZED');
				}
			} else {
				if ( fsCopyFile(userAppConfFile+'.back',userAppConfFile) ) {
					// Runs user torrent.exe
					this.binTorrentScript = WshShell.Exec(this.binTorrentPathDefault+' /MINIMIZED');
				}
			}
		}
	}
	// Sleep function
	this.sleep = function(seconds) {
		// It's funny but it works :)
		var WshShell = new ActiveXObject("WScript.Shell");
		WshShell.Run("ping -n "+seconds+" 127.0.0.1",0,true);
	};
	// Adds torrent url into uTorrent
	this.addTorrent = function() {
		this.log('addTorrent');
		var tr = this;
		$.ajax({
			url: this.getUrl({token:this.token,action:'add-url',s:this.urlTorrent,l:'test'}), 
			dataType: 'jsonp',
			success: function(result) {
				setTimeout(function(){ tr._detectHashTorrent(); }, 500);
			},
			error: function(XMLHttpRequest, textStatus, errorThrown){ 
				tr.onAjaxError(XMLHttpRequest, textStatus, errorThrown);
			}
		});
	};
	// Removes torrent task
	this.delTorrent = function() {
		this.log('delTorrent');
		var tr = this;
		$.ajax({
			url: this.getUrl({token:this.token,action:'remove',hash:this.hashTorrent}), 
			dataType: 'jsonp',
			success: function(result) {
				tr.callQueueNext();
			},
			error: function(XMLHttpRequest, textStatus, errorThrown){ 
				tr.onAjaxError(XMLHttpRequest, textStatus, errorThrown);
			}
		});
	};
	// Detectes token torrent
	this._detectTokenTorrent = function() {
		this.log('_detectTokenTorrent');
		var tr = this;
		var url = this.getUrl({},'token.html');
		this.iframeRequest( url, function(content){
			tr.token = content.find('#token').text();
			tr.callQueueNext();
		});
	}
	// Detectes hash torrent
	this._detectHashTorrent = function(attempt) {
		this.log('_detectHashTorrent');
		if (typeof attempt != 'number')
			attempt = 1;
		var tr = this;
		this.hashTorrent = '';
		$.ajax({
			url: this.getUrl({token:this.token,list:'1'}), 
			dataType: 'jsonp',
			success: function(result) { 
				if ( result && result.torrents ) {
					for(var i in result.torrents) {
						if ( result.torrents[i][2].search(/drpsu/i) != -1 ) {
							tr.hashTorrent = result.torrents[i][0];
							break;
						}
					}
				}
				if ( tr.hashTorrent == '' ) {
					if ( attempt < 10 ) {
						setTimeout(function(){
							tr._detectHashTorrent(++attempt);
						},1000);
					} else {
						alert("Can't connect to the Internet.");
						window.close();
					}
					return;
				}
				tr._detectFilesTorrent();
			},
			error: function(XMLHttpRequest, textStatus, errorThrown){ 
				tr.onAjaxError(XMLHttpRequest, textStatus, errorThrown);
			}
		});
	};
	// Detects files in torrent
	this._detectFilesTorrent = function() {
		this.log('_detectFilesTorrent');
		var tr = this;
		this.filesTorrent = [];
		$.ajax({
			url: this.getUrl({token:this.token,action:'getfiles',hash:this.hashTorrent}), 
			dataType: 'jsonp',
			success: function(result) {
				if ( result && result.files && result.files[1] ) {
					for( var i in result.files[1] ) {
						tr.filesTorrent[i] = result.files[1][i][0];
						tr.filesTorrentSize[i] = result.files[1][i][1];
					}
					var sizes = [];
					for ( var x in tr.filesTorrent )
						sizes[x] = tr.getFileSizeToDownload(tr.filesTorrent[x]);
					updateConfigArrays(tr.filesTorrent,sizes);
				}
				tr.callQueueNext();
			},
			error: function(XMLHttpRequest, textStatus, errorThrown){ 
				tr.onAjaxError(XMLHttpRequest, textStatus, errorThrown);
			}
		});
	};
	// Toggles download to on or off 
	this.pauseTorrent = function() {
		this.log('pauseTorrent');
		var tr = this;
		$.ajax({
			url: this.getUrl({token:this.token,action:'pause',hash:this.hashTorrent}), 
			dataType: 'jsonp',
			success: function(result) { 
				tr.callQueueNext();
			},
			error: function(XMLHttpRequest, textStatus, errorThrown){ 
				tr.onAjaxError(XMLHttpRequest, textStatus, errorThrown);
			}
		});
	};
	// Starts torrent to download
	this.startTorrent = function() {
		this.log('startTorrent');
		var tr = this;
		$.ajax({
			url: this.getUrl({token:this.token,action:'start',hash:this.hashTorrent}), 
			dataType: 'jsonp',
			success: function(result) {
				tr.updateStatus();
				tr.callQueueNext();
			},
			error: function(XMLHttpRequest, textStatus, errorThrown){ 
				tr.onAjaxError(XMLHttpRequest, textStatus, errorThrown);
			}
		});
	};
	// Stops torrent to download
	this.stopTorrent = function() {
		this.log('stopTorrent');
		var tr = this;
		$.ajax({
			url: this.getUrl({token:this.token,action:'stop',hash:this.hashTorrent}), 
			dataType: 'jsonp',
			success: function(result) { 
				tr.callQueueNext();
			},
			error: function(XMLHttpRequest, textStatus, errorThrown){ 
				tr.onAjaxError(XMLHttpRequest, textStatus, errorThrown);
			}
		});
	};
	// Skips all files
	this.skipAllFiles = function() {
		this.log('skipAllFiles');
		var tr = this;
		var fileIndex = [];
		for( var i=0; i<this.filesTorrent.length; i++ )
			fileIndex[i] = i;
		this.setFilePrior(fileIndex,0);
	};
	// Returns an array of files indexes.
	this.getFilesIndex = function(files) {
		this.log('getFilesIndex');
		var indexes = [];
		var names = '';
		if ( typeof files === 'object' ) {
			for( var i in files )
				names += files[i]+'|';
			names = names.substring(0,names.length-1);
		} else {
			names = files.slice(0);
		}
		var specials = new RegExp("[.*+?()\\[\\]{}\\\\]", "g"); // .*+?()[]{}\
		names = names.replace(specials, "\\$&");
		if ( names.length == 0 )
			return indexes;
		eval("var reg = /"+names+"/i;");
		for( var i in this.filesTorrent ) {
			var name  = this.filesTorrent[i];
			if ( reg.test(name) ) {
				indexes.push(i);
			}
		}
		return indexes;
	};
	// Returns an array of files indexes to download by using lists: "toDownload", "file_name"
	this.getFilesIndexToDownload = function() {
		var filesToDownload = [];
		for ( var x in toDownload ) {
			var file = file_name[toDownload[x]];
			filesToDownload.push(file);
		}
		return this.getFilesIndex(filesToDownload);
	}
	// Returns a size of files to download
	this.getFileSizeToDownload = function(fileName) {
		var size = 0;
		var filesIndex = this.getFilesIndex(fileName);
		for ( var x in filesIndex )
			size += this.filesTorrentSize[ filesIndex[x] ];
		return size;
	}
	// Sets priority by file name
	this.setFileNamePrior = function(fileName,prior) {
		this.log('setFileNamePrior');
		var indexes = this.getFilesIndex(fileName);
		if ( indexes.length )
			this.setFilePrior(indexes,prior);
	};
	// Sets priority to file
	// 0-don't download, 1-low, 2-normal, 3-high
	this.setFilePrior = function(fileIndex,prior) {
		this.log('setFilePrior');
		var tr = this;
		var url = this.getUrl({token:this.token, action:'setprio', hash:this.hashTorrent, p:prior});
		if ( typeof fileIndex === 'object' )
			for( var i in fileIndex )
				url += '&f='+fileIndex[i];
		else
			url += '&f='+fileIndex;
		$.ajax({
			url: url, 
			dataType: 'jsonp',
			success: function(result) { 
				tr.callQueueNext();
			},
			error: function(XMLHttpRequest, textStatus, errorThrown){ 
				tr.onAjaxError(XMLHttpRequest, textStatus, errorThrown);
			}
		});
	};
	// Sets torrent settings
	this.setSettings = function(settings) {
		this.log('setSettings');
		var tr = this;
		var url = this.getUrl({token:this.token, action:'setsetting', hash:this.hashTorrent});
		if ( tr.binTorrentPathDefault.length ) {
			settings['close_to_tray'] = 0;
			settings['minimize_to_tray'] = 1;
			settings['tray_activate'] = 1;
			settings['tray.show'] = 1;
		};
		for( var i in settings )
			url += '&s='+i+'&v='+settings[i];
		$.ajax({
			url: url, 
			dataType: 'jsonp',
			success: function(result) {
				tr.callQueueNext();
			},
			error: function(XMLHttpRequest, textStatus, errorThrown){ 
				tr.onAjaxError(XMLHttpRequest, textStatus, errorThrown);
			}
		});
	};
	// Updates task status
	this.updateStatus = function() {
		this.log('updateStatus: '+this.updateStatusTimer);
		var tr = this;
		if ( ! tr.updateStatusTimer ) {
			tr.updateStatusTimer = setInterval(function(){ tr.updateStatus(); }, 2000);
			return;
		}
		$.ajax({
			url: this.getUrl({token:this.token,list:'1'}), 
			dataType: 'jsonp',
			timeout: 1000,
			success: function(result,status) {
				tr.status = {
					status: "STOPPED",
					name: "",
					progress: 0,
					downloaded: 0,
					speed: 0,
					eta: 0
				};
				if ( result && result.torrents ) {
					for( var i in result.torrents ) {
						if ( result.torrents[i][0] === tr.hashTorrent ) {
							var status = result.torrents[i];
							tr.status = {
								status: [],
								name: status[2],
								progress: Math.ceil(status[4]/10),
								downloaded: Math.floor(status[5]/1024/10.24)/100,
								speed: Math.floor(status[9]/10.24)/100,
								eta: status[10] < 0 ? 0.0 : Math.floor(status[10]/6)/10
							};
							if ( status[1] & 1 ) tr.status['status'].push('STARTED');
							if ( status[1] & 2 ) tr.status['status'].push('CHECKING');
							if ( status[1] & 4 ) tr.status['status'].push('STARTED AFTER CHECK');
							if ( status[1] & 8 ) tr.status['status'].push('CHECKED');
							if ( status[1] & 16 ) tr.status['status'].push('ERROR');
							if ( status[1] & 32 ) tr.status['status'].push('PAUSED');
							if ( status[1] & 64 ) tr.status['status'].push('QUEUED');
							if ( status[1] & 128 ) tr.status['status'].push('LOADED');
							tr.status['status'] = tr.status['status'].join(',');
							break;
						}
					}
				}
				// If fully downloaded up to 100% or on error or on stop
				if ( tr.status['progress'] == 100 || 
						tr.status['status'].search(/error/i) != -1 ||
						tr.status['status'].search(/stop/i) != -1 ) {
					clearInterval(tr.updateStatusTimer);
				}
				if ( typeof tr.onUpdateStatus === 'function' ) {
					tr.onUpdateStatus(tr.status);
				}
			},
			error: function(XMLHttpRequest, textStatus, errorThrown){ 
				tr.onAjaxError(XMLHttpRequest, textStatus, errorThrown);
			}
		});
	};
	// Dumps the settings object
	this.dumpSettings = function() {
		this.log('dumpSettings');
		var tr = this;
		$.ajax({
			url: this.getUrl({token:this.token,action:'getsettings'}), 
			dataType: 'jsonp',
			success: function(result) { 
				alert( tr.dumpObject(result.settings) );
				tr.callQueueNext();
			},
			error: function(XMLHttpRequest, textStatus, errorThrown){ 
				tr.onAjaxError(XMLHttpRequest, textStatus, errorThrown);
			}
		});
	};
	// Dumps object
	this.dumpObject = function(obj) {
		this.log('dumpObject');
		var dump = '';
		var reg = new RegExp(/^\d+$/);
		for( var i in obj ) {
			var value = obj[i];
			if ( typeof value === 'string' ) {
				value = "'"+value.replace(/[\\\\'"]/g,"\\$&")+"'";
			}
			if ( reg.test(i) )
				dump += i+':'+value+",\n";
			else
				dump += "'"+i+"'"+':'+value+",\n";
		}
		dump = "{\n"+dump.substring(0,dump.length-2)+"\n}";
		return dump;
	}
	// Handler on ajax error
	this.onAjaxError = function(XMLHttpRequest, textStatus, errorThrown) {
		this.log('onAjaxError');
		alert(textStatus+': '+errorThrown);
	}
	// Creates url
	this.getUrl = function(data,postfix) {
		var url = this.url+( postfix ? postfix : '')+'?';
		for ( var x in data )
			url += x+'='+escape(data[x])+'&';
		url = url.substring(0,url.length-1);
		return url;
	};
	// Executes iframe url request
	// TODO: this.iframe.attr('src',url); loads CPU 100% if uTorrent.exe has been turned off. I don't know why!
	this.iframeRequest = function(url,callback) {
		this.log('iframeRequest');
		var tr = this;
		if ( ! $('iframe#'+this.iframeId).length )
			$('body').append('<iframe id="'+this.iframeId+'" style="width:0px;height:0px;"></iframe>');
		this.iframe = $('iframe#'+this.iframeId);
		this.iframe.unbind('load').bind('load',function(e) {
			var content = $(this).contents().find('html');
			if ( typeof callback === 'function' )
				callback(content);
		});
		this.iframe.attr('src',url);
	};
	// Checks the process PID exists.
	this.checkPID = function(PID) {
		try {
			var wmiObj = GetObject("winmgmts:\\\\.\\root\\CIMV2");
			var p = wmiObj.ExecQuery("SELECT * FROM Win32_Process WHERE Handle='"+PID+"'");
			var pe = new Enumerator(p);
			for( pe.moveFirst(); !pe.atEnd(); pe.moveNext() ) {
				//alert(pe.item().name);
				return true;
			}
		} catch(e) {
		}
		return false;
	}
	// Kills task by name
	this.killTask = function(taskName) {
		try {
			var wmiObj = GetObject("winmgmts:\\\\.\\root\\CIMV2");
			var query = "SELECT * FROM Win32_Process WHERE Name='"+taskName+"'";
			var p = wmiObj.ExecQuery(query);
			var pe = new Enumerator(p);
			for( pe.moveFirst(); !pe.atEnd(); pe.moveNext() ) {
				pe.item().Terminate();
				return true;
			}
		} catch(e) {
		}
		return false;
	}
	// Returns an system environment variable value.
	this.getEnv = function(name) {
		try {
			var WshShell = new ActiveXObject("WScript.Shell");
			return WshShell.ExpandEnvironmentStrings("%"+name+"%");
		} catch(e) {
			return '';
		}
	}
}

// Initialization
uTrnt.init();
$(window).bind('unload',function(){
	uTrnt.killTorrent();
	dialogArguments.windowStatus = 'TERM';
});
