<?php
class ImportController
{
	public $fail;

	private $dbh;
	private $imap;

	private $customers;
	private $version;

	private $currentErrorCount;


	public function __construct ($database, $imap)
	{
		$this->dbh = new PDO($database['connect'], $database['user'], $database['password']);
		$this->dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
		$this->imap = $imap;

		$this->loadCustomers();
	}

	public function Workflow ()
	{
		$this->connectToServer();
		$this->importMails();
		$this->closeConnection();
	}


	private function findAdditionalErrors ($fb, $whiteList)
	{
		$fb = str_replace("\r\`", "`", str_replace("\r\"", "\"", str_replace("\r\n", "", $fb)));
		$report = json_decode($fb, true);

		if (!$report) {
			return addslashes($fb);
		}

		if ($whiteList) {
			if (!isset($whiteList['Layer'])) $whiteList['Layer'] = array();
			if (!isset($whiteList['Report'])) $whiteList['Report'] = array();
			if (!isset($whiteList['User'])) $whiteList['User'] = array();
		}

		foreach ($report as $i => $log) {
			if (preg_match("/\.bat$/", $log['Name'])) {
				$report[$i]['Errors'][0] = htmlentities($report[$i]['Errors'][0]);
				$report[$i]['Errors'][0] = preg_replace("/!! Bitte E-Mailadresse fuer Statusbericht angeben !!/im", "! Bitte E-Mailadresse fuer Statusbericht angeben !", $report[$i]['Errors'][0]);
				$report[$i]['Errors'][0] = preg_replace("/!! SMTP-Konfiguration bitte anpassen !!/im", "! SMTP-Konfiguration bitte anpassen !", $report[$i]['Errors'][0]);
				$count = 0;
				$report[$i]['Errors'][0] = preg_replace("/(!![^\n]*!!)/im", "<b>$1</b>", $report[$i]['Errors'][0], -1, $count);
				$count2 = 0;
				$report[$i]['Errors'][0] = preg_replace("/\((\w{2}\d{4})\)( [^\r]*)/im", "<b><a href='http://gc-server1/wiki/$1' target='_blank'>($1)</a>$2</b>", $report[$i]['Errors'][0], -1, $count2);
				//die(print($log['Errors'][0]));
				if ($count > 0 || $count2 > 0) {
					$report[$i]['ErrorLevel'] = 2;
					for ($j = 1; $j < $count; $j++) {
						$report[$i]['Errors'][] = "";
					}
					$this->currentErrorCount += 1;
				}
			} else if ($whiteList && count($report[$i]['Errors']) > 0 && ($report[$i]['Type'] == 'Versand' || $report[$i]['Type'] == 'Portal')) {
				$report[$i]['Errors2'] = array();
				foreach ($report[$i]['Errors'] as $j => $e) {
					if (in_array($e['Layer'], $whiteList['Layer']) || in_array($e['Report'], $whiteList['Report']) || in_array($e['User'], $whiteList['User'])) {
						$report[$i]['Errors2'][] = $report[$i]['Errors'][$j];
						unset($report[$i]['Errors'][$j]);
					}
				}
				if (count($report[$i]['Errors']) == 0) {
					$report[$i]['ErrorLevel'] = 3;
					$this->currentErrorCount -= 1;
				}
			}
		}
		return addslashes(json_encode($report));
	}

	private function loadCustomers ()
	{
		$q = $this->dbh->query("SELECT kunde, whitelist, version FROM kunden");
		$customerQuery = $q->fetchAll(PDO::FETCH_ASSOC);
		$this->customers = array();
		$this->version = array();
		foreach ($customerQuery as $c) {
			$this->customers[$c['kunde']] = json_decode(stripslashes($c['whitelist']), true);
			$this->version[$c['kunde']] = $c['version'];
		}
	}

	private function connectToServer ()
	{
		$this->fail = false;
		$this->imap['connect'] = imap_open($this->imap['server'], $this->imap['user'], $this->imap['password']) or die("Could not open Mailbox - try again later!");
		$this->imap['message_count'] = imap_num_msg($this->imap['connect']);
		if ($this->imap['message_count'] > 40) {
			$this->imap['message_count'] = 40;
			$this->fail = true;
		}
	}

	private function importMails ()
	{
		for ($m = 1; $m <= $this->imap['message_count']; $m++) {
			$this->currentErrorCount = 0;
			$header = imap_headerinfo($this->imap['connect'], $m);
			$rec = explode(";", $header->Subject);
			
			if ($rec[0] == "=?iso-8859-1?Q?L=B3ckenotto") {
				$rec[0] = "Lueckenotto";
			}

			if (count($rec) < 5) continue;
			if (count($rec) < 6) {
				$rec[] = "";
			}

			$attachments = $this->getAttachments($m, @$this->customers[$rec[0]]);

			$rec[] = $attachments['fehlerbericht'];
			$rec[4] += $this->currentErrorCount;

			/** @noinspection SqlInsertValues */
			$insertQuery = "INSERT INTO status_meldung (kunde, start, ende, datum, anzahl, aufgabe, fehlerbericht) VALUES ('" . implode("','", $rec) . "')";
			$c = $this->dbh->query($insertQuery);
			if ($c) {
				imap_delete($this->imap['connect'], $m);
			} else {
				if (strtotime($header->MailDate) < strtotime("-5 days")) {
					imap_delete($this->imap['connect'], $m);
				}
				$error = $this->dbh->errorInfo();
				if ($error[0] != "23000") {
					print_r($error);					
				}
			}


			if (!isset($this->customers[$rec[0]])) {
				$this->dbh->query("INSERT INTO kunden (kunde) VALUES ('{$rec[0]}')");
				$this->customers[$rec[0]] = array();
			}

			if (substr($rec[5], -4) == ".bat" && !isset($this->customers[$rec[0]][$rec[5]])) {
				$this->dbh->query("INSERT INTO kunden_aufgabe (kunde,aufgabe,start_soll,ende_soll,erster_status) 
											VALUES ('{$rec[0]}', '{$rec[5]}', '{$rec[1]}', '{$rec[2]}', '{$rec[3]}')");
				$this->customers[$rec[0]][$rec[5]]['whitelist'] = false;
			}

			$ver = "";
			if (preg_match("/Version:\s*(\d{4}-\d{2}-\d{2})_?(\w*)?/", $attachments['fehlerbericht'], $ver) && (!isset($version[$rec[0]]) || $version[$rec[0]] != $ver[1])) {
				$beta = ($ver[2] == "beta") ? '1' : '0';
				$this->dbh->query("UPDATE kunden SET version = '{$ver[1]}', beta_version = '{$beta}' WHERE kunde = '{$rec[0]}'");
			}

			if ($attachments['info']) {
				$q = $this->dbh->query("SELECT * FROM kunden_config WHERE kunde = '{$rec[0]}' ORDER BY datum DESC LIMIT 1");
				$last = ($q && $q->rowCount() == 1) ? $q->fetch(PDO::FETCH_ASSOC) : false;
				if (!$last || addslashes($last['info']) != $attachments['info']) {
					$this->dbh->query("INSERT INTO kunden_config (kunde, datum, info) VALUES ('{$rec[0]}', '{$rec[3]}', '{$attachments['info']}')");
				}
			}

			if ($attachments['starter']) {
				$q = $this->dbh->query("SELECT * FROM kunden_gcstarter WHERE kunde = '{$rec[0]}' ORDER BY datum DESC LIMIT 1");
				$last = ($q && $q->rowCount() == 1) ? $q->fetch(PDO::FETCH_ASSOC) : false;
				if (!$last || addslashes($last['gcstarter']) != $attachments['starter']) {
					$this->dbh->query("INSERT INTO kunden_gcstarter (kunde, datum, gcstarter) VALUES ('{$rec[0]}', '{$rec[3]}', '{$attachments['starter']}')");
				}
			}

			if ($attachments['struct']) {
				$q = $this->dbh->query("SELECT * FROM kunden_gcstruct WHERE kunde = '{$rec[0]}' ORDER BY datum DESC LIMIT 1");
				$last = ($q && $q->rowCount() == 1) ? $q->fetch(PDO::FETCH_ASSOC) : false;
				if (!$last || addslashes($last['gcstruct']) != $attachments['struct']) {
					$this->dbh->query("INSERT INTO kunden_gcstruct (kunde, datum, gcstruct) VALUES ('{$rec[0]}', '{$rec[3]}', '{$attachments['struct']}')");
				}
			}
		}
	}

	private function closeConnection () {
		imap_expunge($this->imap['connect']);
		imap_close($this->imap['connect']);
	}

	private function getAttachments ($m, $customer = null)
	{
		$structure = imap_fetchstructure($this->imap['connect'], $m);
		$attachments = array();
		if (isset($structure->parts) && count($structure->parts)) {

			for ($i = 0; $i < count($structure->parts); $i++) {

				$attachments[$i] = array(
					'is_attachment' => false,
					'filename' => '',
					'name' => '',
					'attachment' => ''
				);

				if ($structure->parts[$i]->ifdparameters) {
					foreach ($structure->parts[$i]->dparameters as $object) {
						if (strtolower($object->attribute) == 'filename') {
							$attachments[$i]['is_attachment'] = true;
							$attachments[$i]['filename'] = $object->value;
						}
					}
				}

				if ($structure->parts[$i]->ifparameters) {
					foreach ($structure->parts[$i]->parameters as $object) {
						if (strtolower($object->attribute) == 'name') {
							$attachments[$i]['is_attachment'] = true;
							$attachments[$i]['name'] = $object->value;
						}
					}
				}

				if ($attachments[$i]['is_attachment']) {
					$attachments[$i]['attachment'] = imap_fetchbody($this->imap['connect'], $m, $i + 1);
					if ($structure->parts[$i]->encoding == 3) { // 3 = BASE64
						$attachments[$i]['attachment'] = base64_decode($attachments[$i]['attachment']);
					} elseif ($structure->parts[$i]->encoding == 4) { // 4 = QUOTED-PRINTABLE
						$attachments[$i]['attachment'] = quoted_printable_decode($attachments[$i]['attachment']);
					}
				}
			}
		}

		$result = array(
			'fehlerbericht' => 0,
			'info' => 0,
			'starter' => 0,
			'struct' => 0
		);

		$result['fehlerbericht'] = addslashes(trim(imap_fetchbody($this->imap['connect'], $m, '1')));

		foreach ($attachments as $key => $attachment) {
			if ($attachment['is_attachment']) {
				if ($attachment['filename'] == "info.json") {
					$result['info'] = addslashes($attachment['attachment']);
				}
				if ($attachment['filename'] == "gcstarter.json") {
					$result['starter'] = addslashes($attachment['attachment']);
				}
				if ($attachment['filename'] == "gcstruct.json") {
					$result['struct'] = addslashes($attachment['attachment']);
				}
				if ($attachment['filename'] == "fehlerbericht.json") {
					$result['fehlerbericht'] = $this->findAdditionalErrors($attachment['attachment'], $customer);
				}
			}
		}
		return $result;
	}
}