<?php
require_once(dirname(__FILE__).'/GapsXmlInfoController.php');
require_once(dirname(__FILE__).'/PowerplayController.php');
require_once(dirname(__FILE__).'/MailController.php');
require_once(dirname(__FILE__).'/../models/Logfile.php');

class GapsXmlController
{
	/** @var string  */
	private $today;
	private $generateTypes;

	private $flagSeperateMail = false;
	private $flagSendMail = true;
	private $flagGenImages = true;
	/** @var string  */
	private $publishImagePath;
	/** @var string  */
	private $reportPath;
	/** @var PowerplayController */
	private $pprCtrl;

	private $cubePath;
	private $mailController;

	public static function Run ($argv)
	{
		$config = parse_ini_file(dirname(__FILE__) . "/../../../GAPS.ini");

		if ($argv[1] == "generate") {
			GapsXmlController::Generate($config, $argv);
		} else if ($argv[1] == "cube-pfad") {
			GapsXmlController::UpdateCubePath($config, $argv[2]);
		} else {
			GapsXmlController::Duration($config, $argv);
		}
	}

	public static function Generate ($config, $argv)
	{
		if (count($argv) < 3) {
			die("Aufruf: php Tools\\generate.php generate GAPS.xml [Benutzer,Mails] [Cubes]");
		}
		
		$gapsXmlCtrl = new GapsXmlController($config);		
		$xml = $argv[2];

		if (count($argv) > 3 && ($argv[3] == "mail" || $argv[3] == "pdf")) {
			$gapsXmlCtrl->setAction($argv[3]);
			array_shift($argv);
		}
		$userFilter = (count($argv) > 3 && $argv[3] != "") ? explode(",", strtolower($argv[3])) : array("*");
		$cubeFilter = (count($argv) > 4 && $argv[4] != "") ? explode(",", strtolower($argv[4])) : array("*");


		$gapsXmlCtrl->generateAll($xml, $userFilter, $cubeFilter);
	}

	public static function Duration ($config, $argv)
	{
		if (count($argv) < 3) {
			die("Aufruf: php Tools\\generate.php [duration|summary] GAPS.xml Logdatei");
		}
		$action = $argv[1];
		$newStructure = (substr($action, -1) != "2");
		$xml = $argv[2];
		$xmlInfo = pathinfo($xml);
		$xmlBasename = $xmlInfo['basename'];
		$errorLog = (count($argv) > 3) ? $argv[3] : realpath(dirname(__FILE__) . "\\..\\..\\logs\\" . $xmlBasename . ".log");

		$gapsXmlCtrl = new GapsXmlController($config);
		$result = $gapsXmlCtrl->getStatistics($xml, $newStructure);

		switch ($action) {
			case "duration":
			case "duration2":
				$duration = $result['summary']->Categories;
				$estimate = date("H:i", strtotime("now") + $duration * 60);
				echo "Geschaetzte Dauer: {$duration} Minuten\r\n";
				echo "Geschaetztes Ende: {$estimate}\r\n";
				break;
			case "summary":
			case "summary2":
			default:
				file_put_contents($errorLog, json_encode($result));
				if (count($result['errors']) > 0) {
					echo "Fehlerhafte Dateien (". count($result['errors']) . "):\r\n";
					foreach ($result['errors'] as $e) {
						echo $e . "\r\n";
					}
					echo "\r\nDetails: " . $errorLog ."\r\n";
				}
				break;
		}
	}

	public static function Summary ($config, $argv) {
		GapsXmlController::Duration($config, $argv);
	}

	public static function UpdateCubePath ($config, $xmlFile) {
		$gapsXmlCtrl = new GapsXmlController($config);
		$gapsXmlCtrl->changeCubePath($xmlFile);
		return;
	}

	public function __construct ($config)
	{
		$this->today = strtotime("now") - 12 * 60 * 60;
		$this->generateTypes = array(".gif" => "GIFGenerate", ".pdf" => "PDFGenerate", ".xls" => "XLSGenerate"); //".jpg" => "JPGGenerate",
		$this->flagSeperateMail = (isset($config['VERSAND_SEPARAT']) && $config['VERSAND_SEPARAT'] != "N");
		$this->mailController = new MailController($config);
	}

	public function setAction ($flag) {
		$this->flagGenImages = ($flag != "mail");
		$this->flagSendMail = ($flag != "pdf");
	}
	
	public function getStatistics ($xml, $newFile = true)
	{
		$xmlInfo = pathinfo($xml);
		$xmlBasename = str_replace(".xml", "", $xmlInfo['basename']);
		$doc = simplexml_load_string(file_get_contents($xml));

		$gxiCtrl = new GapsXmlInfoController();
		$reports = $gxiCtrl->getExistingReportFiles($xmlBasename, $doc);

		date_default_timezone_set('UTC');

		$startTime = 0;
		$time = 0;

		$duration = "00:01:00";
		$result = array('errors' => array(), 'sources' => array(), 'summary' => null);


		$publishImagePath = (string)$doc->General->PublishImagePath;
		$reportPath = (string)$doc->General->ReportPath;

		foreach ($doc->Publishes->Publish as $publish) {
			/** @var SimpleXMLElement $publish  */
			$attr = $publish->attributes();
			foreach ($publish->Images->Image as $image) {
				if ($newFile) {
					$dat = $publishImagePath . $xmlBasename . "\\" . (string)$image->Report . "_";
				} else {
					$dat = $publishImagePath . (string)$image->Directory . (string)$attr->Name . "\\" . (string)$image->Name;
				}
				$reportFile = $reportPath . (string)$image->Report;
				if (!file_exists($reportFile . ".ppx")) {
					$reportFile .= ".ppr";
				} else {
					$reportFile .= ".ppx";
				}
				
				if (stripos($reportFile, "_graf") && !file_exists($reportFile)) {
					continue;
				}

				foreach ($this->generateTypes as $extension => $value) {
					if ((string)$image->$value != "J")
						continue;

					$layer = ($extension == ".pdf") ? (string)$image->PDFImageLayer : (string)$image->ImageLayer;
					if ($newFile) {
						$imageFile = $dat . $layer . $extension;
						$imageFileUtf8 = utf8_decode($imageFile);
					} else {
						$imageFile = $dat . $extension;
						$imageFileUtf8 = utf8_decode($imageFile);
					}

					if (file_exists($imageFileUtf8) && filemtime($imageFileUtf8) >= $this->today) {
						if ($startTime) {
							$duration = date("H:i:s", intval(filemtime($imageFileUtf8)) - $time);
						} else {
							$startTime = intval(filemtime($imageFileUtf8));
						}
						$time = intval(filemtime($imageFileUtf8));
					} else {
						$duration = (file_exists($imageFileUtf8)) ? "alt" : "fehlt";

						$modified = (file_exists($imageFileUtf8)) ? date("d.m.Y H:i", filemtime($imageFileUtf8)) : "fehlt";
						$newError = new WorkflowError();
						$newError->Filename = $imageFile;
						$newError->User = substr((string)$image->Directory, 0, -1);
						$newError->Report = (string)$image->Report;
						$newError->ReportModified = (file_exists($reportFile)) ? date("d.m.Y H:i", filemtime($reportFile)) : "fehlt";
						$newError->Cube = (isset($reports[$newError->Report])) ? $reports[$newError->Report] : "";
						$newError->Layer = $layer;
						$newError->MailTo = (string)$image->Email;
						$newError->Modified = $modified;
						$result['errors'][] = $newError;
					}
					$source = new Source($imageFile);
					$source->Report = (string)$image->Report;
					$source->Layer = $layer;
					$source->Duration = $duration;
					$result['sources'][] = $source;
					/*
								<Name>1.2 Kostenstellenbericht aktueller Monat</Name>
								<Description>Kostenstellenbericht aktueller Monat</Description>
								<Directory>Global1\</Directory>
								<Report>1_2_Kostenstellenbericht_aktueller_Monat_Graf</Report>
								<GIFGenerate>J</GIFGenerate>
								<JPGGenerate>N</JPGGenerate>
								<PDFGenerate>N</PDFGenerate>
								<XLSGenerate>N</XLSGenerate>
								<Active>N</Active>
								<SendEmail>N</SendEmail>
								<ImageType>0</ImageType>
								<ImageLayer>0</ImageLayer>
								<PDFImageType>0</PDFImageType>
								<PDFImageLayer>0</PDFImageLayer>
								<Ansicht>Client</Ansicht>
								<Email />
								<ppx>N</ppx>
					*/
				}
			}
		}
		$result['summary'] = new Summary(count($result['sources']), floor(($time - $startTime) / 60) + 1);
		$result['summary']->Duration = date("H:i:s", $time - $startTime);

		date_default_timezone_set('Europe/Berlin');
		return $result;
	}

	public function generateAll ($xmlFile, $userFilter, $cubeFilter)
	{
		$doc = $this->readXmlFile($xmlFile);

		$xmlShortFileName = substr(basename($xmlFile), 0, -4);
		$this->publishImagePath = (string)$doc->General->PublishImagePath . $xmlShortFileName . "\\";
		$this->pprCtrl = new PowerplayController($this->publishImagePath);

		$this->cubePath = (string)$doc->General->CubePath;
		$this->reportPath = (string)$doc->General->ReportPath;

		$reportMapping = $this->getReportMapping($doc, $userFilter, $cubeFilter);

		if ($this->flagGenImages) {
			$this->generateImages($reportMapping['report']);
		}
		if ($this->flagSendMail) {
			$this->sendMails($reportMapping['mail'], $xmlShortFileName);
		}

		$scorecardMapping = $this->getScorecardMapping($doc);
		if (count($scorecardMapping['report']) > 0) {
			$sc = $this->generateScorecards($scorecardMapping);
			$this->saveScorecards($sc);
		}
	}

	public function changeCubePath ($xmlFile)
	{
		$doc = $this->readXmlFile($xmlFile);
		$this->cubePath = (string)$doc->General->CubePath;
		$this->reportPath = (string)$doc->General->ReportPath;
		$this->publishImagePath = (string)$doc->General->PublishImagePath;
		$this->pprCtrl = new PowerplayController($this->publishImagePath);

		$gxiCtrl = new GapsXmlInfoController();
		$reports = $gxiCtrl->getExistingReportFiles("1", $this->reportPath, false, "");		
		
		$reportMapping = $this->getReportMapping($doc);
		//  $reportMapping['report'][$report][$extension] = 1

		foreach($reportMapping['report'] as $report => $reportArray) {
			$ppxFile = $this->reportPath . $report . ".ppx";
			$pprFile = $this->reportPath . $report . ".ppr";
			if (file_exists($ppxFile)) {
				$this->changeCubePathInFile($ppxFile);
			} else if (file_exists($ppxFile)) {
				if ($this->pprCtrl->OpenReport($pprFile, $this->cubePath . $reports[$report] . "mdc")) {
					$this->pprCtrl->Save();
					$this->pprCtrl->CloseReport();
				}
			}
		}
	}

	private function saveScorecards ($sc)
	{
		foreach($sc['data'] as $user => $userArray) {
			$xml = simplexml_load_string('<?xml version="1.0" encoding="iso-8859-1"?><Daten />');

			foreach ($userArray as $id => $idArray) {
				$cat = $xml->addChild("Kategorie");
				/** @var SimpleXMLElement $cat  */
				$cat->addAttribute("ID", $id);
				$cat->addChild("Publish");
				$cat->addChild("Scorecards");

				foreach ($idArray as $e) {
					$entry = $cat->Scorecards->addChild("Bericht");
					/** @var SimpleXMLElement $entry  */
					$scorecard = $sc['report'][$e[0]][$e[1]][$e[2]];

					foreach ($scorecard as $key => $value) {
						$entry->addChild($key, $value);
					}
				}
			}

			$xml->asXML($this->publishImagePath . "..\\" . $user . "\\data.xml");
		}
		/*
		$header = array("Report","Zeile","Spalte","Datum","Wert");
		$recentFile = $this->publishImagePath . "recent.csv";
		$scFile = $this->publishImagePath . "scorecards.csv";

		$handle = fopen($recentFile, "w+");
		fwrite($handle, implode(";", $header) . "\r\n");
		foreach ($sc as $row) {
			fwrite($handle, implode(";", $row) . "\r\n");
		}
		fclose($handle);

		if (!file_exists($scFile)) {
			array_unshift($sc, $header);
		}
		$handle = fopen($scFile, "a+");
		foreach ($sc as $row) {
			fwrite($handle, implode(";", $row) . "\r\n");
		}
		fclose($handle);
		*/
	}

	public function getScorecardMapping($doc)
	{
		$result = array('report' => array(), 'data' => array());

		foreach ($doc->Scorecards->Scorecard as $sc) {
			/** @var SimpleXMLElement $sc */
			$attr = $sc->attributes();
			$id = (string)$attr->ID;
			$user = substr((string)$attr->Directory, 0, -1);
			// $category = (string)$attr->Name;

			foreach ($sc->Reports->Report as $cell) {
				$report = trim((string)$cell->ReportFile);

				$row = (string)$cell->RowData;
				$col = (string)$cell->ColData;
				$format = (string)$cell->Format;
				$result['report'][$report][$row][$col] = array(
					'Titel' => (string)$cell->Name,
					'Beschreibung' => (string)$cell->Description,
					'Wert' => 0,
					'Grafik' => (string)$cell->ReportFile,
					'URL' => "",
					'Format' => $format,
					'HoherZielwert' => (string)$cell->HoherZielwert,
					'NiedrigerWert' => (string)$cell->LowValue,
					'HoherWert' => (string)$cell->HighValue,
					'Koordinaten' => $row . "|" . $col,
					'Toleranz' => (string)$cell->Tolerance,
					'Gewichtung' => (string)$cell->Weight,
					'Akkumulation' => 0,
					'Email' => "",
					'InfoURL' => ""
				);
				$result['data'][$user][$id][] = array($report, $row, $col);


				/* Quelle
				         <Scorecard ID="36420" Directory="Global1\" Name="_4._Service_">
            <Reports>
                <Report ID="88670">
                    <Name>Ergebnis Prognose Monat Service Hannuschka</Name>
                    <Description>Ergebnis Prognose Monat Service Hannuschka</Description>
                    <Active>J</Active>
                    <ReportFile>Prog_Monat_Soll_Ist_Service</ReportFile>
                    <RowData>1</RowData>
                    <ColData>18</ColData>
                    <HoherZielwert>J</HoherZielwert>
                    <LowValue>0.9</LowValue>
                    <HighValue>1.0</HighValue>
                    <Tolerance>0</Tolerance>
                    <Format>Prozent</Format>
                    <Weight>0</Weight>
                    <MonthlyAccumulate>N</MonthlyAccumulate>
                    <Email/>
                    <InfoURL/>
				 */

				/*
				 <Daten>
    <_1._Gesamtbetrieb_ ID="36420">
        <Scorecards>
            <Bericht>
                <Titel>Prognose Ergebnis Gesamt</Titel>
                <Beschreibung></Beschreibung>
                <Wert>109,14 %</Wert>
                <Grafik>images/</Grafik>
                <URL><![CDATA[http://10.6.174.10/GAPS_BMW/Report/1_15_Monatsprognose]]></URL>
                <HoherZielwert>J</HoherZielwert>
                <NiedrigerWert>90 %</NiedrigerWert>
                <HoherWert>100 %</HoherWert>
                <Koordinaten>1|15</Koordinaten>
                <Toleranz>0</Toleranz>
                <Gewichtung>0</Gewichtung>
                <Akkumulation>N</Akkumulation>
                <Email>hotline@freicon.de</Email>
                <InfoURL>www.freicon.de</InfoURL>
            </Bericht>
				 */
			}
		}
		return $result;
	}

	private function readXmlFile ($xmlFile)
	{
		if (!file_exists($xmlFile)) {
			throw new InvalidArgumentException("File '{$xmlFile}' not found");
		}
		return simplexml_load_string(file_get_contents($xmlFile));
	}

	/**
	 * @param SimpleXMLElement $doc
	 * @param array $userFilter
	 * @param array $cubeFilter
	 * @return array
	 */
	public function getReportMapping ($doc, $userFilter = array("*"), $cubeFilter = array("*"))
	{
		$result = array('report' => array(), 'mail' => array());
		$infoCtrl = new GapsXmlInfoController();
		$reportCubes = array();
		if ($cubeFilter[0] != "*") {
			$reportCubes = $infoCtrl->getExistingReportFiles("", $doc, false);
		}
		$flagMailFilter = ($userFilter[0] != "*" && preg_match("/.*@.*\.\w+/", $userFilter[0]));

		foreach ($doc->Publishes->Publish as $publish) {
			/** @var SimpleXMLElement $publish */
			foreach ($publish->Images->Image as $image) {
				$user = substr((string)$image->Directory, 0, -1);
				$mailAddresses = explode(";", strtolower((string)$image->Email));
				foreach ($mailAddresses as $i => $mailAddress) {
					$mailAddresses[$i] = trim($mailAddress);
				}

				if ($flagMailFilter) {
					$mailAddresses = array_intersect($mailAddresses, $userFilter);
					if (count($mailAddresses) == 0) {
						continue;
					}
				}

				$report = trim((string)$image->Report);
				if ($cubeFilter[0] != "*" && isset($reportCubes[$report]) && !in_array($reportCubes[$report], $cubeFilter)) {
					continue;
				}
				foreach ($this->generateTypes as $extension => $generateImageType) {
					if ((string)$image->$generateImageType != "J")
						continue;

					$desc = utf8_decode((string)$image->Description);
					$layer = ($extension == ".pdf") ? (string)$image->PDFImageLayer : (string)$image->ImageLayer;
					$imageFile = utf8_decode("{$report}_{$layer}{$extension}");

					$result['report'][$report][$extension][$layer] = 1;
					if ((string)$image->SendEmail == "J") {
						foreach ($mailAddresses as $mailAddress) {
							$result['mail'][$mailAddress][$this->publishImagePath.$imageFile] = array($desc, $mailAddresses);
						}
					}
				}
			}
		}
		return $result;
	}

	private function generateImages ($reportMapping)
	{
		//  $reportMapping[$report][$extension] = 1

		foreach($reportMapping as $report => $reportArray) {
			if (!$this->openReport($this->reportPath . $report)) {
				continue;
			}

			if (isset($reportArray['.jpg'])) {
				$this->pprCtrl->PublishImages();
			}
			if (isset($reportArray['.pdf'])) {
				$this->pprCtrl->SaveAsPdf("", array_keys($reportArray['.pdf']));
			}
			if (isset($reportArray['.xls'])) {
				$this->pprCtrl->SaveAsXls();
			}
			$this->pprCtrl->CloseReport();
		}
	}

	public function generateScorecards ($scorecardMapping)
	{
		$result = array();
		$now = date("Y-m-d");

		//  $scorecardMapping[$report][$row][$column] = 1

		foreach($scorecardMapping['report'] as $report => $reportArray) {
			if (!$this->openReport($this->reportPath . $report)) {
				continue;
			}
			foreach ($reportArray as $row => $rowArray) {
				foreach ($rowArray as $col => $v) {
					$currentValue = $this->pprCtrl->GetCellValue($row, $col);
					$result[] = array(
						'report' => $report,
						'row' => $row,
						'column' => $col,
						'date' => $now,
						'value' => $currentValue
					);
					$scorecardMapping['report'][$report][$row][$col]['Wert'] = $currentValue;
				}
			}
			$this->pprCtrl->CloseReport();
		}

		return $scorecardMapping;
	}

	private function openReport ($report)
	{
		$ppxFile = $report . ".ppx";
		$pprFile = $report . ".ppr";

		if (!file_exists($ppxFile)) {
			if (!file_exists($pprFile)) {
				return false;
			}
			$this->pprCtrl->OpenReport($pprFile);
			// $this->pprCtrl->SaveAsPpx();
		} else {
			$this->changeCubePathInFile($ppxFile);
			$this->pprCtrl->OpenReport($ppxFile);
		}
		return true;
	}

	public function changeCubePathInFile ($ppxFile)
	{
		$doc = simplexml_load_file($ppxFile);
		/** @var SimpleXMLElement $attr */
		$attr = $doc->PowerPlayReport->PPDSConnection->attributes();
		if ($this->cubePath != (string)$attr->Path) {
			$attr->Path = $this->cubePath;
			$doc->saveXML($ppxFile);
		}
	}

	public function getXmlFileParameters ($xmlFile)
	{
		$doc = $this->readXmlFile($xmlFile);
		$infoCtrl = new GapsXmlInfoController();
		$reportCubes = $infoCtrl->getExistingReportFiles("", $doc, false);

		$reportMapping = $this->getReportMapping($doc);

		$reports = array();
		$users = array();
		$mails = array();


		//  $reportMapping[$extension][$report][$layer][$user] = ($file, $mail)
		foreach ($reportMapping as $ext => $extArray) {
			foreach($extArray as $report => $reportArray) {
				foreach ($reportArray as $layerArray) {
					foreach ($layerArray as $user => $userArray) {
						if ($ext != '.gif') {
							$reports[$report] = @$reportCubes[$report];
						}
						$users[$user] = 1;
						$m = array_flip(explode(";", $userArray['mail']));
						$mails = array_merge($mails, $m);
					}
				}
			}
		}
		return array('users' => array_keys($users), 'mails' => array_keys($mails), 'cubes' => array_unique(array_values($reports)), 'reports' => array_keys($reports));
	}

	private function sendMails ($reportMapping, $xmlFile)
	{
		$xmlFile = str_replace("_", " ", $xmlFile);
		$xmlFile = preg_replace("/gaps/i", "GAPS", $xmlFile);
		
		//  $reportMapping[$mailAddress][$image] = array($desc, $mailAddresses);
		foreach ($reportMapping as $mailAddress => $image) {
			if ($mailAddress == "") continue;
			echo $mailAddress . "\r\n";
			if (!preg_match("/^[a-z0-9_.+-]+@[a-z0-9-]+\.[a-z0-9-.]+$/i", $mailAddress)) {		
				echo "Keine gueltige E-Mail-Adresse!\r\n";
				continue;
			}
		
			if ($this->flagSeperateMail) {
				foreach ($image as $filename => $desc) {
					if (file_exists($filename) && abs(filemtime($filename) - strtotime("now")) < 24 * 60 * 60) {
						$sourceFile = "";
						preg_match("/(.*)_(\d+)\.\w{3}/", basename($filename), $sourceFile);
						$imageFile = $desc[0] . substr($filename, -4);
						$imageDate = date("d.m.Y H:i", filemtime($filename));
						$attachments = array(realpath($filename), $imageFile);
						$descriptions = "<tr><td>{$imageFile}</td><td>{$sourceFile[1]}</td><td>{$sourceFile[2]}</td><td>{$imageDate}</td><td>" . implode("<br/>", $desc[1]) . "</td></tr>";

						$this->mailController->sendMail($mailAddress, $desc[0], $this->getMailBody($descriptions), "", array($attachments));
					}
				}
			} else {
				$attachments = array();
				$descriptions = array();			
				foreach ($image as $filename => $desc) {
					$sourceFile = "";
					preg_match("/(.*)_(\d+)\.\w{3}/", basename($filename), $sourceFile);
					$imageFile = $desc[0] . substr($filename, -4);
					$imageDate = "Heute nicht verf&uuml;gbar.";
					if (file_exists($filename) && abs(filemtime($filename) - strtotime("now")) < 24 * 60 * 60) {
						$attachments[] = array(realpath($filename), $imageFile);
						$imageDate = date("d.m.Y H:i", filemtime($filename));
					}
					$descriptions[] = "<tr><td>{$imageFile}</td><td>{$sourceFile[1]}</td><td>{$sourceFile[2]}</td><td>{$imageDate}</td><td>" . implode("<br/>", $desc[1]) . "</td></tr>";
				}
				$count = count($attachments);
				$subject = ($count != 1) ? "{$xmlFile}: {$count} Dateien" : $desc[0];

				$this->mailController->sendMail($mailAddress, $subject, $this->getMailBody(implode("\r\n", $descriptions)), "", $attachments);
			}
		}
	}
	
	private function getMailBody ($content) {
		return "<!DOCTYPE html>\r\n" .
				"<html><head>\r\n" .
				'<meta content="text/html; charset=utf-8" http-equiv="Content-Type"><style>' .
				"\r\n.liste { border: 1px solid #888888; border-collapse: collapse; } \r\n" .
				".liste td, .liste th { padding: 3px 15px; border: 1px solid #888888; } \r\n" .
				"</style></head><body>\r\n" . 
				'<table class="liste"><tr><th>Datei</th><th>Bericht</th><th>Schicht</th><th>Stand</th><th>Empf&auml;nger</th></tr>' . 
				$content .
				"</table></body></html>";
	}
}
?>