<?php
/*
ПРЕДОПРЕДЕЛЕННЫЕ ПЕРЕМЕННЫЕ
$ModDir			- путь до папки мода
$PacksDir		- путь до папки с pkg архивами игры
$AppDataDir		- путь до папки %APPDATA%\wargaming.net\World of Warplanes\
$GameDir		- путь до папки с игрой
$ScriptName		- имя этого файла скрипта
$fn_toLog		- функция добавления сток в отчёт об установке мода
$continue = true	- если после выполнения скрипта будет false, то дальнейшая установка мода прекратится
//*/

// locales
$lngs = array(
	0=>array('СКАЧАТЬ','DOWNLOAD'),
	1=>array('Выделить всё','Select all'),
	2=>array('Снять выделение','Deselect all'),
	3=>array('Найти обновления','Find updates'),
	4=>array('Загрузка обновлений','Download updates'),
	5=>array('Моды не найдены!','Updates not found!'),
	6=>array('Мод предназначен для поиска и загрузки обновлений.','Here you can download the updates.'),
	7=>array('Готово.','Done.'),
	8=>array('Удалить все моды','Remove all mods'),
	9=>array('Вы уверены, что хотите УДАЛИТЬ все моды? (кроме автообновления)','Really?'),
	10=>array('Внимание!','Attention!'),
	11=>array('Точно?','Sure?'),
	12=>array('Удалено:','Removed:'),
	
);

// свои функции
$fn_getElXML = function(&$xml, $xpath){		// взять первый элемент из запроса xpath 
	$result = $xml->xpath($xpath);
	if(!is_array($result) || sizeof($result) == 0) return false;
	return $result[0];
};
$fn_alert = function($txt='',$return=true){	// для отладки
	//echo mb_convert_encoding( $txt.PHP_EOL, 'cp866', 'cp1251' );
	alert($txt);
	return $return;
};
$LNG = function($index)use(&$lngs){
	return $lngs[$index][Lang::$id];
};

/* DEBUG
$ModDir = getcwd();
$ScriptName = basename(__FILE__);
$fn_toLog = function($txt, $ret=null)use(&$fn_alert){return $fn_alert($txt,$ret);};
include '../../Files/scripts/ThreadsMultiCurl.phb';
include '../../Files/scripts/pclzip.lib.phb';
TMC::Init();


//*/


$Const['SERVER_NAME'] = 'roxblnfk.16mb.com';
$Const['SERVER_PATH'] = 'http://'.$Const['SERVER_NAME'].'/wowp/xml.xml';
$Const['DL_PRE_PATH'] = 'http://'.$Const['SERVER_NAME'].'/wowp/';



$TMCProcess = true;
$fn_xml_pase = 'function';	// определена ниже
$fn_download = 'function';	// определена ниже
$fn_CreateWindow = 'function';	// определена ниже
$fn_START = 'function';	// определена ниже
$fn_DELETE = 'function';	// определена ниже
$XML = 'xml будет тут';
$fn_EndFunc = function($tmc_id,$but_id)use(&$fn_alert,&$fn_toLog,&$fn_xml_pase,&$XML,&$TMCProcess,&$LNG){
	$TMCProcess=false;
	//$fn_alert('Поток '.$tmc_id.' завершил выполнение.');
	$ch_info = curl_getinfo(TMC::$PostMC[$tmc_id]);
	if($ch_info['redirect_count'] > 0){	// защита от редирректов
		$fn_alert('Непредвиденное поведение ресурса обновлений. Обновите программу вручную из первоисточника.');
		c($but_id)->enabled = true;
		return false;
	}
	if($ch_info['size_download'] > 1024*1024){	// ограничение в 1MiB
		$fn_alert('Загружаемый файл версий слишком большой. Что-то тут не так!');
		c($but_id)->enabled = true;
		return false;
	}
	if($ch_info['size_download'] == 0){	// не сакчано ни чего
		$fn_alert('Ресурс не доступен!');
		c($but_id)->enabled = true;
		return false;
	}
	$content = curl_multi_getcontent(TMC::$PostMC[$tmc_id]);
	if(strtolower(substr(ltrim($content),0,5))!=='<?xml'){
		$fn_alert('Файл не доступен. Попробуйте ещё.');
		c($but_id)->enabled = true;
		return false;
	}
	$XML = new SimpleXMLElement($content);
	unset($content);
	//
	c($but_id)->visible = false;
	TRGUI::$ModsGlobals['!primary update!']['win']['components']['butDelet']->visible = false;
	$fn_xml_pase();
};


$fn_xml_pase = function()use(&$fn_alert,&$fn_toLog,&$XML,&$fn_getElXML,&$ModDir,&$fn_download,&$fn_CreateWindow,&$LNG){
	//$fn_alert('Парсим XML');
	$comp = &TRGUI::$ModsGlobals['!primary update!']['win']['components'];
	$upd_opt = array('visible'=>true);
	if(TRGUI::SoftVersion < floatval($fn_getElXML($XML, '//root/soft/version'))){
		if(mrYes !== messageBox("Программа WoWP Manager нуждается в обновлении!\r\nОбновить программу?",$LNG(10),MB_YESNO)) return false;
		// UPDATE SOFT!
		//$upd_opt['base_dir'] = str_replace('\\','/',realpath($ModDir.'/../../')).'/'.'/down/';
		$upd_opt['base_dir'] = str_replace('\\','/',realpath($ModDir.'/../../')).'/';
		$upd_opt['visible'] = false;	// не отображать список файлов
		$upd_opt['filelist'] = $fn_getElXML($XML, '//root/soft/files');
		$xfiles = $upd_opt['filelist']->children();
		for($i=sizeof($xfiles)-1;$i>=0;--$i){	// качать по умолчанию!
			$xfiles[$i]->download = true;
		}
		if($fn_download($upd_opt)) $fn_alert('Перезапустите программу!');
		else {
			$fn_alert('Вы можете попробовать загрузить обновления ещё раз, может повезёт...');
			$comp['butStart']->enabled = true;
			$comp['butStart']->visible = true;
			$comp['lbl2']->visible = false;
		}
		return true;
	}else{
		// UPDATE MODS
		//$upd_opt['base_dir'] = str_replace('\\','/',realpath($ModDir.'/../'.'../')).'/down/';
		$upd_opt['base_dir'] = str_replace('\\','/',realpath($ModDir.'/../')).'/';
		$upd_opt['filelist'] = $fn_getElXML($XML, '//root/mods/files');
		$xfiles = $upd_opt['filelist']->children();
		$ModsList = array();
		$ModsText = array();
		$ModNames = array();
		$cnt = 0;
		$ksn = array('Название','Кол-во файлов','Размер (байт)');
		for($i=sizeof($xfiles)-1;$i>=0;--$i){
			$xfiles[$i]->download = false;	// по умолчанию не качать
			$modName = trim(strval($xfiles[$i]->mod));
			//$xfiles[$i]->path = base64_encode(base64_decode($modName).'/'.base64_decode($xfiles[$i]->path));
			
			// исключаем имеющееся
			$file_write = $upd_opt['base_dir'].base64_decode($xfiles[$i]->path).'/'.base64_decode($xfiles[$i]->name);
			if(is_file($file_write))
			if(filesize($file_write) === intval(trim($xfiles[$i]->size)))
			if(md5_file($file_write) === trim(strtolower($xfiles[$i]->md5)))
			continue;
			
			if(!isset($ModNames[$modName])){
				$ModNames[$modName] = $cnt;
				$ModsList[$cnt++] = array($ksn[0]=>base64_decode($modName),$ksn[1]=>0,$ksn[2]=>0);
			}
			$id=$ModNames[$modName];
			// название мода
			//$ModsList[$id][0] =$modName;
			// кол-во файлов
			$ModsList[$id][$ksn[1]]++;
			// суммарный размер
			$ModsList[$id][$ksn[2]]+=intval(trim($xfiles[$i]->size));
			
			$ModsText[$id]=$ModsList[$id][$ksn[0]].'  -  '.$ModsList[$id][$ksn[1]].' файлов, '._sizeFormat($ModsList[$id][$ksn[2]]);
		}
		
		
		if($cnt==0){
			$comp['lbl2']->visible = true;
			$comp['lbl2']->caption = 'Новые моды не найдены!';
			$comp['butStart']->enabled = true;
			$comp['butStart']->visible = true;
			$comp['butDelet']->visible = true;
			return true;
		}
		$fn_mathSelected = function()use(&$comp,&$ModNames,&$upd_opt,&$ModsList,&$ksn,&$LNG){
			$arr=$comp['grid']->checkedItems;
			$modKeys=array_keys($arr);
			$names = array_flip($ModNames);
			
			$files = 0;
			$sizes = 0;
			for($mi=sizeof($modKeys);--$mi>=0;){
				$id=$modKeys[$mi];
				$modName = $names[$id];
				$files+=$ModsList[$id][$ksn[1]];
				$sizes+=$ModsList[$id][$ksn[2]];
			}
			$comp['lbl3']->caption = "Файлов: $files\r\nРазмер: "._sizeFormat($sizes);
		};
		$comp['butSelAll']->visible = true;
		$comp['butSelAll']->onClick=function($id)use(&$comp,&$cnt,&$fn_mathSelected){
			for($i=0;$i<$cnt;++$i)
				$comp['grid']->setChecked($i,true);
			$fn_mathSelected();
		};
		$comp['butDeSelAll']->visible = true;
		$comp['butDeSelAll']->onClick=function($id)use(&$comp,&$cnt,&$fn_mathSelected){
			for($i=0;$i<$cnt;++$i)
				$comp['grid']->setChecked($i,false);
			$fn_mathSelected();
		};
		$comp['butDownload']->visible=true;
		$comp['butDownload']->enabled=true;
		$comp['butDownload']->onClick = function($id)use(&$comp,&$ModNames,&$fn_alert,&$xfiles,&$fn_download,&$upd_opt,&$LNG){
			if(sizeof($arr=$comp['grid']->checkedItems)==0) return $fn_alert('Ни чего не выбрано.',false);
			$comp['grid']->visible = false;
			$comp['butDownload']->enabled=false;
			$comp['butSelAll']->enabled=false;
			$comp['butDeSelAll']->enabled=false;
			
			$modKeys=array_keys($arr);
			$names = array_flip($ModNames);
			
			for($mi=sizeof($modKeys);--$mi>=0;){
				$modName = $names[$modKeys[$mi]];
				//alert(base64_decode($modName));
				for($i=sizeof($xfiles)-1;$i>=0;--$i){
					if(trim($xfiles[$i]->mod) !== $modName) continue;
					$xfiles[$i]->download = true;
				}
			}
			
			$fn_download($upd_opt);
			$comp['butDownload']->enabled=true;
			$comp['butSelAll']->enabled=true;
			$comp['butDeSelAll']->enabled=true;
			$comp['grid']->visible = true;
			
			TRGUI::readModsDir();
			TRGUI::modsToList();
			// снять выделение в памяти
			for($i=sizeof($xfiles)-1;$i>=0;--$i) $xfiles[$i]->download = false;
		};
		$comp['lbl3']->visible = true;
		$comp['lbl3']->caption = '';
		$comp['grid']->onClick = $fn_mathSelected;
		$comp['grid']->onKeypress = $fn_mathSelected;
		$fn_mathSelected();
		
		
		$comp['grid']->visible = true;
		$comp['grid']->text = $ModsText;
		//$comp['grid']->setArray($ModsList);
	}
};
$fn_download = function(&$upd_opt)use(&$fn_alert,&$fn_toLog,&$XML,&$fn_getElXML,&$Const,&$LNG){
	$comp = &TRGUI::$ModsGlobals['!primary update!']['win']['components'];
	$comp['lbl2']->visible = true;
	$comp['lbl2']->caption = 'Подготовка...';
	TRGUI::$ModsGlobals['!primary update!']['win']['form']->repaint();
	
	$xfiles = $upd_opt['filelist']->children();
	$txt='';
	$COUNT = 0;		// нужно скачать
	$CURRENT = 0;	// качается
	$fps = array();
	for($i=sizeof($xfiles)-1;$i>=0;--$i){	// проходим по списку файлов
		$f = &$xfiles[$i];
		if(!(int)$f->download) continue;
		// проверка
		$file_write = $upd_opt['base_dir'].base64_decode($f->path).'/'.base64_decode($f->name);
		if(is_file($file_write))
		if(filesize($file_write) === intval(trim($f->size)))
		if(md5_file($file_write) === trim(strtolower($f->md5)))
		continue;	// файл есть и он совпадает, качать не надо
		
		// назначаем файл на кач
		++$COUNT;
		_mkdir(dirname($file_write));	// оздать папку, если её нет
		
		//alert($Const['DL_PRE_PATH'].base64_decode($f->url)); return;
		
		if(false===($fps[$i] = fopen($file_write,'wb+'))){
			$txt.=PHP_EOL.'Не удалось открыть для записи файл "'.base64_decode($f->name).'"';
			continue;
		}
		++$CURRENT;
		flock($fps[$i], LOCK_EX);
		$fn_EndFunc = function($tmc_id, $i, $file_write)use(&$CURRENT,&$COUNT,&$txt,&$xfiles,&$fps){
			$f = &$xfiles[$i];
			if(is_resource($fps[$i])){
				flock($fps[$i], LOCK_UN);
				fclose($fps[$i]);
			}
			// проверка
			$ch_info = curl_getinfo(TMC::$PostMC[$tmc_id]);
			if(/* (int)$ch_info['size_download'] */ filesize($file_write) !== intval(trim($f->size))){
				$txt.=PHP_EOL.'Не совпадает ожидаемый размер файла с фактическим: "'.base64_decode($f->mod)
					.'/'.base64_decode($f->name).'", (Ожидалось: '
						.intval(trim($f->size)).', загружено: '.filesize($file_write).')';
				//alert(print_r($ch_info, true));
			}
			--$CURRENT;
			TRGUI::$UI['Progress']->position +=1;
		};
		/// FFUUUUUUuuuu
		$tmc_id = TMC::NewThread(array($Const['DL_PRE_PATH'].base64_decode($f->url)),$fn_EndFunc,array($i,$file_write));
		//alert(1);
		TMC::CurlSetOpt($tmc_id, CURLOPT_FILE, $fps[$i]);
		//TMC::CurlSetOpt($tmc_id, CURLOPT_RETURNTRANSFER, 0);
		TMC::Go($tmc_id);
	}
	//$fn_alert('Файлов к загрузке: '.$CURRENT);
	if($CURRENT==0){
		if(strlen($txt)==0) return $fn_alert('Загрузка файлов не потребовалась.', true);
	} else {
		TRGUI::$UI['Progress']->max = $CURRENT;
		TRGUI::$UI['Progress']->position=0;
		$comp['lbl2']->caption = 'Загрузка...';
		TRGUI::$ModsGlobals['!primary update!']['win']['form']->repaint();
		while($CURRENT){TMC::Process(); usleep(10000);}
		
		for($i=sizeof($fps);--$i>=0;)
			if(is_resource($fps[$i])){
				flock($fps[$i], LOCK_UN);
				fclose($fps[$i]);
			}
	}
	$comp['lbl2']->caption = $LNG(7);
	if(strlen($txt)>0){
		$fn_alert($txt);
		$txt = '';
		return false;
	} else return $fn_alert($LNG(7), true);
};

$fn_CreateWindow = function()use(&$fn_START,&$fn_DELETE,&$LNG){
	if(!isset(TRGUI::$ModsGlobals['!primary update!']) or !is_array(TRGUI::$ModsGlobals['!primary update!']))
			TRGUI::$ModsGlobals['!primary update!'] = array();
	$ModsGlobals = &TRGUI::$ModsGlobals['!primary update!'];
	
	if(isset($ModsGlobals['win']) and is_array($ModsGlobals['win'])){
		if($ModsGlobals['active']) return false;
		
		$form = &$ModsGlobals['win']['form'];
		$comp = &$ModsGlobals['win']['components'];
		$ks = array_keys($comp);
		for($i=sizeof($ks);--$i>=0;){//чистка формы
			// $comp[$ks[$i]]->free();
			// $comp[$ks[$i]]=false;
			// unset($comp[$ks[$i]]);
			$comp[$ks[$i]]->visible = true;
			$comp[$ks[$i]]->enabled = true;
		}
	} else {	// NEW WINDOW
		$ModsGlobals['win'] = array(
				'form'=>false,
				'components'=>array()
			);
		$form = &$ModsGlobals['win']['form'];
		$comp = &$ModsGlobals['win']['components'];
		$form = new TForm();
		$form->clientWidth=600;
		$form->borderStyle=bsSingle;//bsSizeToolWin;//bsToolWindow;//bsSingle;//bsNone;
		$form->caption=$LNG(4);
		//$form->doubleBuffered=true;
		$form->transparentColor=false;
		$form->formStyle=fsStayOnTop;
		$form->h=410;
		$form->w=610;
		$form->x=TRGUI::$Form->x;
		$form->y=TRGUI::$Form->y;
			
		$comp[$c='lbl1'] = TRGUI::createLabel($form,5,5,400,20,$LNG(6));
		$comp[$c='lbl2'] = TRGUI::createLabel($form,5,80,400,60,$LNG(5),null,fsBold,15);
		$comp[$c='lbl3'] = TRGUI::createLabel($form,295,335,150,40,'');
		$comp[$c='butStart'] = TRGUI::createButton($form,5,25,200,60,$LNG(3),fsBold);
			$comp[$c]->onClick = $fn_START;
		$comp[$c='butDelet'] = TRGUI::createButton($form,215,25,200,60,$LNG(8),fsBold);
			$comp[$c]->onClick = $fn_DELETE;
		// $comp[$c='grid'] = new TStringGrid();
			// $comp[$c]->parent = $form;
			// $comp[$c]->x=5;
			// $comp[$c]->y=25;
			// $comp[$c]->w=590;
			// $comp[$c]->h=300;
			// $comp[$c]->colCount = 3;
			// $comp[$c]->fixedCols = 0;
			// $comp[$c]->fixedRows = 1;
			// $comp[$c]->rowSelect = true;
			// $comp[$c]->defaultRowHeight = 16;
			// $comp[$c]->colSizing = true;
			// $comp[$c]->defaultColWidth = 180;
			//setArray
		$comp[$c='grid'] = new TCheckListBox();
			$comp[$c]->parent = $form;
			$comp[$c]->x=5;
			$comp[$c]->y=25;
			$comp[$c]->w=590;
			$comp[$c]->h=300;
			$comp[$c]->flat = false;
			$comp[$c]->columns = 0;
			//$comp[$c]->font->style=$style;
			//$comp[$c]->font->color=$color;
			$comp[$c]->font->size=10;
		$comp[$c='butSelAll'] = TRGUI::createButton($form,5,335,140,40,$LNG(1));
		$comp[$c='butDeSelAll'] = TRGUI::createButton($form,150,335,140,40,$LNG(2));
		$comp[$c='butDownload'] = TRGUI::createButton($form,450,335,145,40,$LNG(0), fsBold);
		
		
		$form->onClosequery = function($id,&$canClose)use(&$ModsGlobals){ $canClose=false; c($id)->hide(); $ModsGlobals['active'] = false; };
	}
	$ModsGlobals['active'] = true;
	
	$form->show();
	
	$comp['grid']->visible = false;
	$comp['lbl2']->visible = false;
	$comp['lbl3']->visible = false;
	$comp['butSelAll']->visible = false;
	$comp['butDeSelAll']->visible = false;
	$comp['butDownload']->visible = false;
};
// курлим
$fn_START = function($but_id)use(&$Const,&$fn_EndFunc,&$TMCProcess){
	$TMCProcess=true;
	c($but_id)->enabled = false;
	$tmc_id = TMC::NewThread(array($Const['SERVER_PATH']), $fn_EndFunc, $Pars=array($but_id));
	TMC::Go($tmc_id);
	while($TMCProcess){ usleep(10000); TMC::Process(); }
};
$fn_DELETE = function($but_id)use(&$LNG,&$Const,&$fn_EndFunc,&$TMCProcess,&$ModDir){
	if(mrYes !== messageBox($LNG(9),$LNG(10),MB_YESNO)) return false;
	if(mrYes !== messageBox($LNG(11),$LNG(10),MB_YESNO)) return false;
	$dir = str_replace('\\','/',($ModDir.'/../')).'/';
	if(!is_dir($dir)) return false;
	$list = scandir($dir);
	$txt = $LNG(12);
	for($i=0,$j=sizeof($list);$i<$j;++$i){
		$name = $list[$i];
		if($name == '.' || $name == '..') continue;
		if($name{0} === '!' && $name{strlen($name)-1} === '!') continue;
		if(!is_dir($dir.$name)) continue;
		_rmdir($dir.$name);
		$txt .= "\n$name";
	}
	TRGUI::readModsDir();
	TRGUI::modsToList();
	alert($txt);
};

$fn_CreateWindow();

$continue = false;
?>