<?php
/**
 *  This file is part of open3A.

 *  open3A is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.

 *  open3A is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.

 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  2007 - 2020, open3A GmbH - Support@open3A.de
 */
class DatanormImportGUI extends UnpersistentClass {
	private $texte = array();
	private $ArtikelID = 0;
	public $csvArtikel = array();
	public $csvPreis = array();
	public $lookup = array();
	public $updatePreis = array();
	
	public function __construct() {
		$this->customize();
	}
	
	public function redeemer($mwst, $lieferantID, $prefix){
		set_time_limit(3000);
		if($mwst == "-1"){
			unset($_SESSION["TempFiles"]);
			Red::alertD("Bitte wählen Sie einen MwSt-Satz");
		}
		
		if($lieferantID == "0"){
			unset($_SESSION["TempFiles"]);
			Red::alertD("Bitte wählen Sie einen Lieferanten.");
		}
		
		if(!isset($_SESSION["TempFiles"]))
			Red::alertD("Keine Uploads gefunden!");
		
		$C = $_SESSION["TempFiles"]->getCollector();# AS $k => $v){
		$v = $C[0];
		#print_r($C);
		if(stripos($v->A("filename"), ".exe") !== false){
			unset($_SESSION["TempFiles"]);
			Red::alertD("Bitte laden Sie eine Datanorm-Datei hoch.");
		}
		
		/*if(count($C) > 1){
			unset($_SESSION["TempFiles"]);
			Red::errorD("Dieser Import unterstützt nur eine Datei pro Upload");
		}*/
		
		if(stripos($v->A("filename"), ".zip") !== false AND stripos($v->A("filename"), "_Files") === false){
			$zip = new ZipArchive;
			if ($zip->open($v->A("filename")) === TRUE) {
				$zip->extractTo($v->A("filename")."_Files/");
				$zip->close();
				unlink($v->A("filename"));
			} else {
				unlink($v->A("filename"));
				unset($_SESSION["TempFiles"]);
				Red::alertD("Beim Entpacken der Datei ist ein Fehler aufgetreten.");
			}
			
			$_SESSION["TempFiles"] = new ArrayCollection();
			$this->findFiles($v->A("filename")."_Files/");
			$C = $_SESSION["TempFiles"]->getCollector();
			//Red::alertD("Bitte laden Sie eine Datanorm-Datei hoch.");
		}
		
		
		echo "<p class=\"prettyTitle\">Datanorm-Import</p>";
		echo "<p>Bitte wählen Sie die zu importierende Datei:</p>";
		
		$L = new HTMLList();
		foreach($C AS $v){
			
			$counter = array();
			$handle = fopen($v->A("filename"),"r");
			if(filesize($v->A("filename")) < 60 * 1024 * 1024)
				while($data = fgetcsv($handle, 1000, ";")){
					if($data[0][0] == "V")
						continue;

					if(!isset($counter[$data[0]]))
						$counter[$data[0]] = 0;

					$counter[$data[0]]++;
				}
		
			$list = "";
			foreach($counter AS $b => $c)
				$list .= ($list != "" ? ", " : "")."$b: $c";
			
			$L->addItem("<a href=\"#\" onclick=\"".OnEvent::popup("Datanorm-Import", "DatanormImport", "-1", "action", array("'".str_replace("\\", "/", $v->A("filename"))."'", "'$mwst'", "'$lieferantID'", "'$prefix'"), "", "{width: 800}")."\">".str_replace(".tmp", "", basename($v->A("filename")))."</a> <span style=\"color:grey;\">($list) ".Util::formatByte($v->A("filesize"))."</span>");
		}
		
		echo $L;
		
		$BC = new Button("Import\nbeenden", "stop");
		$BC->rmePCR("DatanormImport", "-1", "clearCache", "", "function(){ ".OnEvent::closePopup("DatanormImport")." }");
		$BC->style("margin:10px;");
		
		echo $BC;
	}
	
	private function findFiles($dir){
		$dir = new DirectoryIterator($dir);
		foreach ($dir as $file) {
			if($file->isDot())
				continue;
			
			if($file->isDir()) {
				$this->findFiles($file->getPathname());
				return;
			}
			
			if(getimagesize($file->getPathname()) !== false)
				continue;
			
			$T = new TempFile();
			$A = $T->newAttributes();
			$A->filename = $file->getPathname();
			$A->filesize = $file->getSize();
			$T->setA($A);
			
			$_SESSION["TempFiles"]->add($T);
		}
	}
	
	function clearCache($dir = null){
		if(!$dir)
			$dir = Util::getTempDir();
		
		if(strpos($dir, Util::getTempDir()) === false)
			return;
		
		unset($_SESSION["TempFiles"]);
		
		$dir = new DirectoryIterator($dir);
		foreach ($dir as $file) {
			if($file->isDot())
				continue;
			
			if($file->isDir()) {
				$this->clearCache($file->getPathname());
				rmdir($file->getPathname());
				return;
			}
			
			unlink($file->getPathname());
		}
	}
	
	function action($file, $mwst, $lieferantID, $prefix){
		if(!file_exists($file))
			Red::errorD("Die Datei wurde nicht gefunden");
		
		$bpsName = "lastLine".Util::makeFilename(basename($file));
		$bpsCount = "lastCount".Util::makeFilename(basename($file));
		$bpsByte = "lastByte".Util::makeFilename(basename($file));
		
		$T = new HTMLTable(5);#, "Datanorm-Import");
		$T->setColWidth(1, 20);
		$T->setColWidth(2, 150);
		$T->setColWidth(4, 100);
		$T->setColWidth(5, 70);
		$T->maxHeight(400);
		
		$lastLine = BPS::getProperty("DatanormImportAlgo", $bpsName, 0);
		$row = $lastLine;
		$i = 0;
		$skipped = 0;
		$broke = false;

		$count = BPS::getProperty("DatanormImportAlgo", $bpsCount, null);
		if($count == null){
			$handle = fopen($file,"r");
			if ($handle) {
				while (fgets($handle) !== false)
					$count++;

				#if (!feof($handle)) {
				#	echo "Error: unexpected fgets() fail\n";

				fclose($handle);
			}
			
			BPS::setProperty("DatanormImportAlgo", $bpsCount, $count);
		}
		
		$DB = new DBStorage();
		$DB->lockTable(array("Artikel", "LieferantPreis", "Rabattgruppe", "Kategorie"));
		
		
		#$C->query("CREATE TABLE datanormImportArtikel ENGINE=MEMORY SELECT ArtikelID, artikelnummer FROM Artikel");
		#echo $C->error;
		
		#$DB->lockTable(array("datanormImportArtikel"));
		$breakAmount = 1000;
		
		$AC = anyC::get("Artikel");
		$AC->addOrderV3("ArtikelID", "DESC");
		$AC->setLimitV3(1);
		$Artikel = $AC->n();
		if($Artikel != null)
			$this->ArtikelID = $Artikel->getID();
		
		$handle = fopen($file,"r");
		fseek($handle, BPS::getProperty("DatanormImportAlgo", $bpsByte, 0));
		$data = fgetcsv($handle, 1000, ";");
		
		while($data !== false) {
			$nextData = fgetcsv($handle, 1000, ";");

			$row++;

			#if($lastLine > $row)
			#	continue;
			
			if($data[0] == "B" OR $data[0] == "Z") {
				$data = $nextData;
				$row --;
				$skipped++;
				continue;
			}
			
			if($data[0][0] == "V") {
				$data = $nextData;
				continue;
			}

			$tabCon = array($data[0], "nicht", "unterstützt", "", "");
			
			#if($data[0] == "B")
			#	$tabCon = $this->handleB($data, $mwst, $lieferantID, $prefix);
			#echo $data[0];
			if($data[0] == "P"){
				$tabCon = $this->handleP($data, $mwst, $lieferantID, $prefix, $file);
				$breakAmount = 500;
			}
			
			if($data[0] == "A"){
				$tabCon = $this->handleA($data, $mwst, $lieferantID, $prefix);
				
				if($nextData[0] == "B")
					$this->handleB($nextData, $lieferantID, $prefix);
				
			}
			
			if($data[0] == "R")
				$tabCon = $this->handleR($data, $lieferantID, $prefix);
			

			$T->addRow($tabCon);
			if(isset($tabCon[5]) AND $tabCon[5] === false)
				$T->addRowStyle("color:grey;");

			$data = $nextData;
			if($row - $lastLine == $breakAmount AND $data !== false) {
				$broke = true;
				break;
			}
			
			$i++;
		}
		#SysMessages::i()->echoMessagesReverse();
		
		Aspect::joinPoint("alter", $this, __METHOD__, array($DB->getConnection()));
		
		if(count($this->csvArtikel)){
			$C = $DB->getConnection();
			
			$nr = "";
			foreach($this->csvArtikel AS $artikel)
				if(trim($artikel[1]) != "")
					$nr .= ($nr != "" ? "," : "")."'".$C->real_escape_string($artikel[1])."'";
			#echo "<br>";
			#echo $nr;
			$sql = "SELECT ArtikelID, artikelnummer, preis FROM Artikel WHERE artikelnummer IN($nr);";
			$Q = $C->query($sql);
			if($C->error){
				echo "Datanorm: ".$C->error."<br>";
				echo $sql;
			}
			
			while($T = $Q->fetch_object()){
				foreach($this->csvArtikel AS $key => $artikel)
					if(trim($artikel[1]) != "" AND $artikel[1] == $T->artikelnummer){
						#echo "skip '$artikel[1]' '$T->artikelnummer'<br>";
						unset($this->csvArtikel[$key]);
						if(isset($this->csvPreis[$key])){
							$this->updatePreis[$key] = $this->csvPreis[$key];
							unset($this->csvPreis[$key]);
						}
					}
			}
			
			if(count($this->csvArtikel))
				$DB->makeNewLines(
					"Artikel",
					array("ArtikelID", "artikelnummer", "name", "beschreibung", "preis", "gebinde", "isBrutto", "mwst", "EAN", "artikelnummerHersteller"),
					$this->csvArtikel);
		}
		
		if(count($this->csvPreis))
			$DB->makeNewLines(
				"LieferantPreis",
				array("LieferantPreisLieferantID", "LieferantPreisArtikelID", "LieferantPreisListenPreis", "LieferantPreisRabattgruppe"),
				$this->csvPreis);
		
		if(count($this->updatePreis))
			foreach($this->updatePreis AS $key => $val)
				$this->updatePreis($key, 0, $val[2] * 100, $mwst, $lieferantID, "", $file); //prefix is already in $key
		
		
		$DB->unlockTables();
		
		if(count($this->lookup)){
			$C = $DB->getConnection();
			
			$Q = $C->query("SHOW INDEX FROM LieferantPreis WHERE key_name LIKE 'datanorm';");
			$R = $Q->fetch_object();
			if(!$R)
				$C->query("ALTER TABLE `LieferantPreis` ADD INDEX `datanorm` (`LieferantPreisLieferantID`, `LieferantPreisArtikelID`);");
			
			$Q = $C->query("SHOW INDEX FROM Artikel WHERE key_name LIKE 'datanorm';");
			$R = $Q->fetch_object();
			if(!$R)
				$C->query("ALTER TABLE `Artikel` ADD INDEX `datanorm` (`artikelnummer`);");

			
			$nr = "";
			foreach($this->lookup AS $k => $v)
				$nr .= ($nr != "" ? "," : "")."'".$C->real_escape_string($k)."'";

			$Q = $C->query("SELECT ArtikelID, artikelnummer FROM Artikel WHERE artikelnummer IN($nr);");
			echo $C->error;
			
			while($T = $Q->fetch_object())
				$this->lookup[$T->artikelnummer] = str_replace ("%ArtikelID%", $T->ArtikelID, $this->lookup[$T->artikelnummer]);
			
			foreach($this->lookup AS $v){
				if(strpos($v, "%ArtikelID%") !== false)
					continue;
				$C->query($v);
				#echo $v;
				echo $C->error;
			}
			/*if($C->multi_query(implode("\n", $this->lookup))){
				do {
					
				} while($C->next_result());
				
			}*/
			
			#echo $C->multi_query(implode("\n", $this->lookup));
			#echo $C->error;
		}
		
		#$C->query("DROP TABLE datanormImportArtikel");
		BPS::setProperty("DatanormImportAlgo", $bpsByte, ftell($handle));
		BPS::setProperty("DatanormImportAlgo", $bpsName, $row + $skipped);
		
		fclose($handle);

		$end = "";
		$reload = "";
		$BC = "";
		if(!$broke){
			#unset($_SESSION["TempFiles"]);
			BPS::unsetProperty("DatanormImportAlgo", $bpsName);
			BPS::unsetProperty("DatanormImportAlgo", $bpsCount);
			BPS::unsetProperty("DatanormImportAlgo", $bpsByte);

			$B = new Button("Import abgeschlossen", "bestaetigung");
			$B->type("icon");
			$B->style("float:left;margin-right:10px;");

			$BC = new Button("OK", "bestaetigung");
			$BC->popup("", "Datanorm-Import", "DatanormImport", "-1", "redeemer", array("'$mwst'", "'$lieferantID'", "'$prefix'"), "", "{width: 800}");
			#$BC->onclick(OnEvent::closePopup("DatanormImport"));
			$BC->style("float:right;margin:10px;");
			
			$end = "<p>".$BC.$B."Der Import der Datei <b>".basename($file)."</b> wurde erfolgreich abgeschlossen.</p>";
		} else {
			$B = new Button("Import wird fortgesetzt", "navigation");
			$B->type("icon");
			$B->style("float:left;margin-right:10px;");

			#$T->addRow("<div style=\"width:".ceil(($row/$count) * 100)."%;text-align:center;\" class=\"confirm\"><div style=\"padding:10px;\">".ceil(($row/$count) * 100)."%</div></div>");
			#$T->addCellStyle(1, "padding:0px;");
			#$T->addRowColspan(1, 5);
			#$T->addRowClass("backgroundColor0");

			$end = "<div style=\"width:".ceil(($row/$count) * 100)."%;text-align:center;\" class=\"confirm\"><div style=\"padding:10px;\">".ceil(($row/$count) * 100)."%</div></div>";
			$end .= "<p>".$B."Bitte haben Sie Geduld, während der Import durchgeführt wird.<br>$row/$count</p>";
			#$T->addRow(array($B."Bitte haben Sie Geduld, während der Import fortgesetzt wird.<br />$row/$count"));
			#$T->addRowColspan(1, 5);
			#$T->addRowClass("backgroundColor0");
			#$T->addCellStyle(1, "color:grey;");
			
			#$reload = "<script type=\"text/javascript\">contentManager.loadFrame('contentLeft', 'DatanormImport');</script>";
			
			$reload = OnEvent::script(OnEvent::rme($this, "action", array("'$file'", "'".$mwst."'", "'".$lieferantID."'", "'".$prefix."'"), "function(t){ \$j('#editDetailsContentDatanormImport').html(t.responseText); }"));
		}
		
		#Timer::now("end", __FILE__, __LINE__);
		echo $end."<div style=\"clear:both;height:20px;\"></div>".$reload;
	}
	
	public static function fixdata($data){
		$data = str_replace(array("", "", "", "", "", "á"), array("ö", "Ö", "ü", "Ü", "ä", "ß"), $data);

		return $data;
	}

	private function handleP($data, $mwst, $lieferantID, $prefix, $file){
		$this->updatePreis($data[2], $data[3], $data[4], $mwst, $lieferantID, $prefix, $file);
		if(isset($data[11]))
			$this->updatePreis($data[11], $data[12], $data[13], $mwst, $lieferantID, $prefix, $file);
		if(isset($data[20]))
			$this->updatePreis($data[20], $data[21], $data[22], $mwst, $lieferantID, $prefix, $file);

		return array("P", "$data[1] <span style=\"float:right;\">".Util::CLFormatCurrency($data[4]/100)."</span>", isset($data[11]) ? "$data[11]: ".Util::CLFormatCurrency($data[13]/100) : "", isset($data[20]) ? "$data[20]: ".Util::CLFormatCurrency($data[22]/100) : "", "", true);
	}

	private function updatePreis($artikelnummer, $kennzeichen, $preis, $mwst, $lieferantID, $prefix, $file = ""){ //$file is used for customizer
		// <editor-fold defaultstate="collapsed" desc="Aspect:jP">
		try {
			$MArgs = func_get_args();
			return Aspect::joinPoint("around", $this, __METHOD__, $MArgs);
		} catch (AOPNoAdviceException $e) {}
		Aspect::joinPoint("before", $this, __METHOD__, $MArgs);
		// </editor-fold>
		
		if($artikelnummer == "")
			return;
		
		$p = $preis / 100;

		if($kennzeichen == "2")//Bruttopreis
			$p = $p / (100 + $mwst) * 100;
		
		$this->lookup[$prefix.$artikelnummer] = "UPDATE LieferantPreis SET LieferantPreisListenPreis = '$p' WHERE LieferantPreisLieferantID = '$lieferantID' AND LieferantPreisArtikelID = '%ArtikelID%';";
	}

	private function handleT($data){
		if(!isset($this->texte[$data[2]]))
			$this->texte[$data[2]] = "";
		
		$this->texte[$data[2]] .= $data[5]."\n";
	}
	
	private function handleB($data, $lieferantID, $prefix){
		#echo "B";
		#sleep(3);
		/*echo "<pre>";
		print_r($data);
		foreach($this->csvArtikel AS $k => $v){
			echo $k."($prefix$data[2]):";
			print_r($v);
			break;
		}*/
		#echo "HI";
		#print_r($this->csvArtikel);
		#echo "</pre>";
		#echo $prefix.$data[2]."<br>";
		if(!isset($this->csvArtikel[$prefix.$data[2]])) //probably already processed or A;A!
			return;
		#echo "HO";
		#echo "<pre>";
		#print_r($this->csvArtikel);
		#echo "</pre>";
		
		$this->csvArtikel[$prefix.$data[2]][8] = $data[9];
		$this->csvArtikel[$prefix.$data[2]][9] = $data[3];
		
		#print_r($this->csvArtikel);
		
		return array("B", $data[2], $data[9], "", "", true);
	}
	
	private function handleR($data, $lieferantID, $prefix){
		$F = new Factory("Rabattgruppe");
		$F->sA("RabattgruppeNummer", $data[2]);
		$F->sA("RabattgruppeLieferantID", $lieferantID);

		$E = $F->exists(true);
		if($E !== false){
			$F = new Factory("Rabattgruppe", $E->getID());
			$F->sA("RabattgruppeNummer", $data[2]);
		}

		$F->sA("RabattgruppeKennzeichen", $data[3]);
		$F->sA("RabattgruppeWert", $data[4]);
		$F->sA("RabattgruppeName", self::fixdata(utf8_encode($data[5])));

		$F->store();

		return array("R", $data[2], $data[3], (float)$data[4] / (float)100, self::fixdata(utf8_encode($data[5])), true);
	}

	private function handleA($data, $mwst, $lieferantID, $prefix){
		#echo "A";
		$tabCon = array();
		switch($data[1]){
			case "N":
				
				$preiseinheit = 1;
				if($data[7] == "1")
					$preiseinheit = 10;
				if($data[7] == "2")
					$preiseinheit = 100;
				if($data[7] == "3")
					$preiseinheit = 1000;

				$name = self::fixdata(utf8_encode($data[4]));
				$beschreibung = self::fixdata(utf8_encode($data[5]));
/*if ($data[9] != 0) {
                   $preis = $data[9] / 100;
                }else{
                   $preis = 0;
                }
*/
 
                                $preis = (float)$data[9] / (float)100; 
				$gebinde = utf8_encode(($preiseinheit != 1 ? $preiseinheit." " : "").$data[8]);

				$tabCon = array($data[1], $prefix.$data[2], $name, "<span style=\"float:right;\">".Util::CLFormatCurrency($preis * 1)."</span>", $gebinde, true);


				/*$ArtikelID = $F->exists();
				if($ArtikelID) {
					$tabCon[5] = false;
					$FP->sA("LieferantPreisArtikelID", $ArtikelID);

					$LP = $FP->exists();
					if($LP === false){
						$FP->sA("LieferantPreisListenPreis", $preis);
						$FP->sA("LieferantPreisRabattgruppe", $data[10]);

						$FP->store();
					}

					return $tabCon;
				}*/
				
				$EAN = "";
				if(isset($data[19]))
					$EAN = $data[19];
				
				$HART = "";
				if(isset($data[13]))
					$HART = $data[13];
				
				$this->csvArtikel[$prefix.$data[2]] = array(
					++$this->ArtikelID,
					$prefix.$data[2],
					trim($name),
					trim($beschreibung), //3
					$preis,
					trim($gebinde),
					"0", //6
					$mwst,
					$EAN,
					$HART);
				
				$this->csvPreis[$prefix.$data[2]] = array(
					$lieferantID,
					$this->ArtikelID,
					$preis,
					$data[10]
				);
				
				/*$F = new Factory("Artikel");
				$F->sA("artikelnummer", $prefix.$data[2]);
				$F->sA("name", $name);
				$F->sA("beschreibung", $beschreibung);
				$F->sA("preis", $preis);
				$F->sA("gebinde", $gebinde);
				$F->sA("isBrutto", "0");
				$F->sA("mwst", $mwst);*/
				
				#Timer::now("handle 1", __FILE__, __LINE__);
				
				#$ArtikelID = $F->store();
				#Timer::now("handle 2", __FILE__, __LINE__);

				#$FP = new Factory("LieferantPreis");
				#$FP->sA("LieferantPreisLieferantID", $lieferantID);
				#$FP->sA("LieferantPreisArtikelID", $ArtikelID);
				#$FP->sA("LieferantPreisListenPreis", $preis);
				#$FP->sA("LieferantPreisRabattgruppe", $data[10]);
				
				#$FP->store();
				
				#Timer::now("handle 3", __FILE__, __LINE__);
				
				#foreach($data AS $k => $v)
				#	print utf8_encode($v) . "<br />";
			break;
			
			case "L":
				$Artikel = anyC::getFirst("Artikel", "artikelnummer", $prefix.$data[2]);
				
				if($Artikel == null)
					return array($data[1], $prefix.$data[2], "Artikel nicht gefunden", "", "", false);
				
				$AC = anyC::get("LieferantPreis", "LieferantPreisLieferantID", $lieferantID);
				$AC->addAssocV3("LieferantPreisArtikelID", "=", $Artikel->getID());
				while($LP = $AC->getNextEntry())
					$LP->deleteMe();
				
				
				$LP = anyC::getFirst("LieferantPreis", "LieferantPreisArtikelID", $Artikel->getID());
				if($LP === null)
					$Artikel->deleteMe ();
				
				return array($data[1], $prefix.$data[2], $Artikel->A("name"), "gelöscht", "", true);
			break;
		}
		
		return $tabCon;
	}
}
?>
