<?php

session_start();

require("../functions.php");

error_reporting(E_ALL);
ini_set('display_errors', 1);

$db = new SQLite3('../db-test/test.db');

//Befehl zum Starten des Skripts
$command = escapeshellcmd('python3 /var/www/html/python/observer-full.py');

//output1 und bridges1 sind die Ergebnisse des ersten Durchlaufs
$output1 = json_decode(shell_exec($command), true);
$bridges1 = $output1["data"];

//Zeigt schon der Erste durchlauf Fehler auf, kann abgebrochen werden (1. Fehlerfall)
if($output1["logs"]["errorcode"] != 10) {
	?>
	<h3>
		Die Prüfung konnte nicht abgeschlossen werden. <i>Fehler <?php echo $output1["logs"]["errorcode"]; ?></i>
	</h3>
	<?php 
	include("../errorcodes.php");
	die();
}

//wenn bis hierhin ok: weitere Prüfung
$output2 = json_decode(shell_exec($command), true);
$bridges2 = $output2["data"];

//Die Messungen sind nicht identisch (egal ob wg Fehlercodes oder Daten, ungleiche Messungen sind immer schlecht) -> 2. Fehlerfall
//es wäre schon sehr eigenartig, wenn verschiedene Fehlercodes nacheinander ausgespuckt würden (Wackelkontakt?)
if($bridges1 !== $bridges2) {

	measurementsDiffer($bridges1, $bridges2);

}

// Isoliere die Brücken und speichere sie als $bridges (hiermit wird später alles weitere verarbeitet)
$bridges = array_map(function($entry) {
	return $entry[0];  
}, $bridges1);

//Isoliere die Fehlercodes der ersten Messung; da Messungen identisch reicht erste Messung
$errors = array_filter($bridges1, function($entry) {
	return $entry[1] !== 0;
});

//Wenn Fehlerspeicher gefüllt: Ausgabe und Abbruch
if (!empty($errors)) {
	
	measurementsContainErrors($bridges1);
	
}

// ----------
//Ab hier wird die Logik geprüft, die Messung ist bis hierhin äußerlich in Ordnung
// ----------


//Hier wird jetzt geprüft, dass jede Messung bidirektional aufgenommen wurde, also 10<>20 UND 20<>10
$doubles = []; // Array zur Verfolgung von Doppelungen
$errors = [];  // Array für fehlende Doppelungen

// Untersuche die einzelnen aufgenommenen Messpaare
foreach ($bridges as $pair) {
	// Jedes Paar MUSS aus zwei Elementen bestehen
	if (count($pair) !== 2) {
		$errors[] = $pair; // speichere diesen fehlerhaften Eintrag
		continue;
	}
	// Sortiere die Paare, um [23,14] und [14,23] gleich zu behandeln
	sort($pair);
	// Setze dieses Paar als "Index", um es gleich wieder zu finden
	$key = implode("-", $pair);
	// Prüfe, ob dieser Eintrag schon einmal da war
	if (isset($doubles[$key])) {
		$doubles[$key]++; // Verbindung erneut gefunden
	} 
	else {
		$doubles[$key] = 1; // Erstmaliges Auftreten
	}
}
// Überprüfe, ob jede Verbindung genau zweimal vorhanden ist
foreach ($doubles as $key => $count) {
	if ($count !== 2) {
		$errors[] = $key;
	}
}

// Abbruch bei fehlenden Doppelungen
if (!empty($errors)) {
	echo "Die Messung wurde zwar erfolgreich abgeschlossen, die Messergebnisse überzeugten jedoch nicht.<br>Es ist notwendig, dass Kabelbrücken aus beiden Richtungen erkannt werden.<br>Erwägen Sie, eine erneute Messung durchzuführen. Sollte der Fehler erneut auftreten, ist ein interner Defekt des Prüfgeräts wahrscheinlich.<br><br>Die folgende(n) Kabelbrücke(n) konnte(n) nur one-way gemessen werden: <br>";
		print_r($errors);
	
	?>
	<div class="save-button" onclick="window.location.href='#index'; pageload();$('.save-button').html('<img src=\'load.gif\' \>Bitte warten...');"><img src="/vendor/icons/nav-arrow-left.svg" \>Zurück</div>
	<?php
    die(); // Skript abbrechen
}


// ----------
//Die Messung ist valide. Es kann ausgegeben werden
// ----------

// Bereinigung der doppelten Einträge
$unique = []; // Array für eindeutige Verbindungen
$seen = [];   // Array zur Verfolgung bereits bearbeiteter Verbindungen

foreach ($bridges as $pair) {
	// Sortiere das Paar
	sort($pair);
	$key = implode("-", $pair);

	// Füge nur ein Exemplar hinzu
	if (!isset($seen[$key])) {
		$unique[] = $pair;
		$seen[$key] = true; // Markiere als verarbeitet
	}
}

//Wichtigste Variable - sieht z.b. so aus: [[20,30],[10,15]] - redundanzfrei und aufsteigend sortiert
$measurement_result = translateArray($unique, $translationMap);
$measurement_result_number = count($measurement_result); // Anzahl gemessener Brücken



//Haupt-Steckergrafik
$url = 'stecker.php?data=' . urlencode(json_encode($measurement_result));

?>

<div class="content-header">Ergebnis</div>
<hr />
<div class="toggle-switch">
	<div align="right"><p>Gesamtergebnis</p></div>
	<div>
		<label class="switch">
			<input type="checkbox" onchange='$("#op-1").toggle(this.unchecked);$("#op-2").toggle(this.checked);'>
			<span class="slider"></span>
		</label>
	</div>
	<div align="left">
		<p>Einzelbrücken</p>
	</div>
</div>
<div id="op-1">
	<img src="<?php echo $url; ?>" />
</div>
<div id="op-2" style="display: none;">
	<?php

	foreach($measurement_result as $bridge) {
		// Hier muss der übertragene Wert unschön manuell in [] gesetzt werden, da ein äußeres, indexiertes Array erwartet wird...
		?>
		<img style="margin-bottom: 5px;" src="<?php echo 'stecker.php?data=' . urlencode("[" . json_encode($bridge) . "]"); ?>" />
		<?php
	}
	?>
</div>
<hr />
<h2>Identifizierte Brücken</h2>
<?php

//Hole aktuellen Stecker aus der JSON-Datei
$settings = json_decode(file_get_contents("../settings.json"), true);
$plug = $settings["plug"];

$identified_bridges = [];

//Hole alle Nodes via JOIN aus der Dankebak
$nodes = $db->query("
	SELECT 
		b.id AS bridge_id,
		n.node_from,
		n.node_to
	FROM 
		bridges b
	JOIN 
		nodes n ON b.id = n.required_by
	ORDER BY 
		b.id 
");


/*
Ausgabe sieht z.B. so aus:

| bridge_id | node_from | node_to |
| --------- | --------- | ------- |
| 1         | 20        | 30      |
| 1         | 13        | 17      |
| 2         | 10        | 15      |

*/

//die DB-ausgbe wird als indexiertes Array gespeichert, um einfacher durchsucht werden zu können
$bridges_db = [];
while ($row = $nodes->fetchArray(SQLITE3_ASSOC)) {
	//Die Bridge-ID ist der Index, die geforderten Brücken werden im Standardformat eingefügt, z.B.: 1 => [[20,30],[13,17]]
	$bridge_id = $row['bridge_id'];
	$bridges_db[$bridge_id][] = [$row['node_from'], $row['node_to']];
}

//Vergleiche Datenbank mit gemessenen Werten
//iteriere durch alle Datenabnk-Brücken
foreach($bridges_db as $bridge_db => $required_nodes) {
	$satisfied = true;
	//iteriere durch alle von einer Brücke geforderten Node-Paare
	foreach($required_nodes as $required_nodes_pairs) {
		$innerMatch = 0;
		// vergleiche die aktuelle Datenbank-Node mit allen gemessenen Nodes (+überkreuz)
		for($i=0;$i<$measurement_result_number;$i++) { 
			if(($required_nodes_pairs[0] == $measurement_result[$i][0] &&  $required_nodes_pairs[1] == $measurement_result[$i][1] )||($required_nodes_pairs[1] == $measurement_result[$i][0] &&  $required_nodes_pairs[0] == $measurement_result[$i][1])){
				// innerhalb der Node-zu-Node-Verbidnung wurde die Bedingung erfüllt
				$innerMatch = 1; 
			}
		}
		if($innerMatch != 1) { 
			// An dieser Stelle wird satisfied direkt negiert, da mind. eine Abhängigkeit, die in der Datenbank gefordert ist, nicht gefunden wurde
			$satisfied = false;
		}
	}
	// Kommen alle Nodes vor, wird die Brücke mit ihrem entsprechenden Namen dargestellt
	if($satisfied == true) { 
		//Brücke vollständig enthalten -> speichern für später (Programm-Erkennung)
		$identified_bridges[] = $bridge_db;
		
		//Erinnerung: es gilt bridge_db=>bridges_db
		$url = '../stecker.php?data=' . urlencode(json_encode($bridges_db[$bridge_db])); // URL parsen
		?>
		<div class="row">
			<?php
			print('<div class="label"><span>' . $bridge_db . '</span></div>');
			print('<img id="bridge-editor-img" src="' . $url . '" />');
			?>
		</div>
		<?php
	}
}

//Speicher für identifizierte Programme
$identified_programs = [];

//Hole Programme aus der Datenbank (via program_bridge_relation)
$programs = $db->query("
	SELECT 
		p.id AS program_id,
		p.program_description,
		b.id AS bridge_id,
		r.plug_id
	FROM 
		program_bridge_relation r
	JOIN programs p ON p.id = r.program_id
	JOIN bridges b ON b.id = r.bridge_id
	WHERE r.plug_id = '" . $plug . "'
");


/*
Ausgabe sieht z.B. so aus:

| program_id | program_description | bridge_id |
| ---------- | ------------------- | --------- |
| 1          | Weiche, die...      | 1         |
| 2          | Gs, die...          | 1         |
| 2          | Gs, die...          | 10        |

*/


$bridges_db = [];
while ($row = $programs->fetchArray(SQLITE3_ASSOC)) {
	// Gleiches vorgehen wie bei den Brücken: Programm-ID ist Index, Brücken sind Inhalt (2 => [1,10])
	$program_id = $row['program_id'];
	$programs_db[$program_id][] = $row['bridge_id'];
	$program_descriptions[$program_id] = $row['program_description'];
}


//Ist eine Stelle der Kennung des Programmsteckers zwischendrin doppelt beschrieben woren, wird idse Variable wahr
$double_program_identifier = false;


?>
<hr />
<h2>Identifizierte Programme</h2>
<div class="plug-table">
	<?php
	$program_cache = ["?","?","?","?","?"]; // Die Steckerbezeichnung ist zu Beginn noch unbestimmt
	
	//iteriere durch alle DB-Programme
	foreach($programs_db as $program_db => $required_bridges) {
		
		if(!empty($identified_bridges)) { //Abscicherung, sonst würde ein leeres Programm immer als vollständig enthalten markiert werden
			$ok = 1;
		}
		else {
			$ok = 0;
		}
		
		// Iteriere durch alle geforderten Brücken
		foreach ($required_bridges as $bridge_id) {
			// sollte sich eine Programmbrücke nicht unter den identifizierten Messwerte befinden -> ok=0
			if (!in_array($bridge_id, $identified_bridges)) { 
				$ok = 0;
			}
		}
		
		// Programm ist mit allen Brücken vollständig vertreten
		if($ok == 1) {

			?>
			<div class="row">
				<div class="label" style="width: 30%">
					<span>
						<?php
						// Stelle die einzelnen Programmziffern dar, indemdiese aus der DB geladen werden
						$program_identifiers = $db->query("SELECT * FROM program_id_bits WHERE program_id = '" . $program_db . "' ORDER BY position;");	

						while ($program_identifier = $program_identifiers->fetchArray(SQLITE3_ASSOC)) {
							echo '<span class="label-char">' . $program_identifier["value"] . '</span>';
							if($program_identifier["value"] != "" && $program_identifier["value"] != "-") { // wenn noch nicht anders beschrieben oder leer -> Einfügen in großen "Gesamtspeicher" für später
								if($program_cache[$program_identifier["position"]] == "?") {
									$program_cache[$program_identifier["position"]] = $program_identifier["value"];
								}
								else {
									// Wenn Stelle schon gesetzt war -> Warnung speichern
									$double_program_identifier = true;
								}
							}
							$i++;
						}
						?>
					</span>
				</div>
				<?php
				
				$url = '../stecker.php?translate=true&data=' . urlencode(json_encode($required_bridges)); // URL parsen
				print('<img id="bridge-editor-img" style="width: 55%" src="' . $url . '" />');
				
				?>
				
			</div>
			<div class="row" style="position: relative;box-sizing: border-box;padding-left: 45px;">
				<img style="max-height: 100%;width: auto;display: inline-block;filter: opacity(.5);position: absolute;left:10px" src="/vendor/icons/info-circle.svg" style=" top: 2.5px;left: 10px;">
				<?php echo $program_descriptions[$program_db]; ?>
				
			</div>
			<?php
		}
	}
	?>
</div>

<hr />
<h2>Kennungs-Nummer</h2>
<div class="plug-table" style="margin-bottom: 0;">
	<div class="row">
		<div class="label" style="width: 180px;float: none">
			<span>
				<?php
				// Die Gesamt-Kennung-Nummer wurde zuvor von den identifizierten Programmen bestimmt und wird hier ausgegeben
				$ok = 1;
				foreach($program_cache as $cacheChar) {
					echo '<span class="label-char">' . $cacheChar . '</span>';
					if($cacheChar == "?") {
							$ok = 0;
					}
				}
				?>
			</span>
		</div>
	</div>
</div>
<?php
if($ok != 1) {
	?>
	<p style='color: red !important'>
		Wichtiger Hinweis: Es sind nicht alle Stellen der Kennungsnummer definiert. Dies deutet darauf hin, dass möglicherweise nicht alle Programme des Steckers korrekt erkannt wurden. Andererseits kann auch die Programm-Datenbank unvollständig sein, sodass eine Erkennung nicht möglich ist.<br>Betrachten Sie daher das Ergebnis mit Vorsicht!
	</p>
	<?php
}
if ($double_program_identifier == true) {
	?>
	<p style='color: red !important'>
		Wichtiger Hinweis: Im Laufe der Programmabgleiche wurde versucht, eine Stelle der Gesamtkennungsnummer zu übeschreiben, da diese bereits durch ein vorheriges Programm festgelegt wurde. Details dazu finden Sie unter "Indentifizierte Programme". Bitte gleichen Sie die Spalten ab, ob eine doppelte Stellendefinition vorliegt!<br>Betrachten Sie daher das Ergebnis mit Vorsicht!
	</p>
	<?php
}
?>
<hr />
<h2>Identische Messungen</h2>
<div class="inventory-table">

	<?php
	
	//Hole vorherige Messungen aus der DB
	$measurement_nodes_db = $db->query("
		SELECT 
			m.id AS measurement_id,
			m.comment AS comment,
			m.timestamp AS timestamp,
			m.place_name AS place_name,
			n.node_from AS node_from,
			n.node_to AS node_to
		FROM 
			measurements m
		JOIN places p ON p.name = m.place_name
		JOIN measurement_nodes n ON m.id = n.required_by
		ORDER BY m.id
	");

	/*
	Ausgabe sieht z.B. so aus:

	| measurement_id | comment | timestamp  | place_name           | node_from | node_to | 
	| -------------- | ------- | ---------- | -------------------- | --------- | ------- |
	| 1              | abc     | 1753357680 | Mannheim-Waldhof Wf  | 20        | 26      |
	| 1              | abc     | 1753357680 | Mannheim-Waldhof Wf  | 13        | 16      |
	| 1              | abc     | 1753357680 | Mannheim-Waldhof Wf  | 30        | 35      |
	| 2              | def     | 1753357548 | Dudweiler Df         | 30        | 35      |
	| 2              | def     | 1753357548 | Dudweiler Df         | 10        | 12      |

	*/

	// Auch hier werden alle Messungen erstmal komplex indexiert (also zwei ineinander indexierte Arrays): measurement_id=>(nodes=>[[30,35],[10,12]], place_name, timestamp, comment)
	$measurements_db = [];
	while ($row = $measurement_nodes_db->fetchArray(SQLITE3_ASSOC)) {
		$measurement_id = $row['measurement_id'];
		$measurements_db[$measurement_id]['nodes'][] = [$row['node_from'],$row['node_to']];
		$measurements_db[$measurement_id]['place_name'] = $row['place_name'];
		$measurements_db[$measurement_id]['timestamp'] = $row['timestamp'];
		$measurements_db[$measurement_id]['comment'] = $row['comment'];
	}

	//Indikator, dass alle Brücken gefunden wurden
	$ok = 0;

	foreach ($measurements_db as $measurement_db) {
		$satisfied = true;

		foreach ($measurement_result as $bridge_measure) {
			$found = false;

			foreach ($measurement_db["nodes"] as $measurement_db_node) {
				// Prüfe, ob Brücke identisch (+ überkreuz)
				if (
					($bridge_measure[0] == $measurement_db_node[0] && $bridge_measure[1] == $measurement_db_node[1]) ||
					($bridge_measure[0] == $measurement_db_node[1] && $bridge_measure[1] == $measurement_db_node[0])
				) {
					$found = true; // Brücke gefunden
					break; // Nächste Brücke prüfen
				}
			}

			if (!$found) {
				// Diese Brücke nicht in DB gefunden -> Messung nicht erfüllt
				$satisfied = false;
				break; // weitere Brücken prüfen sinnlos
			}
		}

		if ($satisfied) {
			$ok = 1;
			
			?>
			<div class="row">
				<img src="/vendor/icons/map-pin.svg" class="map">
				<span>
					<?php
					echo $measurement_db["place_name"];
					?>
				</span>
				<?php
		
				if(!empty($measurement_db["comment"])) {
				?>
				<img src="/vendor/icons/info-circle.svg" style="top: 30px;" class="map">
				<span>
					<?php
					echo $measurement_db["comment"];
					?>
				</span>
				<?php
				}
				?>

				<div class="plug-table" style="display: block;">
					<div class="row" style="margin-bottom:0;    height: 57px;">
						<div>
							<div class="label" style="width: 100%;height:auto;">
								<span>
			  
									<?php
									echo "Messung vom/um <b>" . date('d.m.Y H:i:s',$measurement_db["timestamp"]) . "</b>";
									?>
								</span>
							</div>
						</div>
					</div>
				</div>
			</div>
			<?php
		}
	}

	?>
</div>

<?php

//Wenn keine Messungen gefunden:
if($ok == 0) {
	?>
	<p>Keine bekannt.</p>
	<?php
}

?>

<hr />

<h2>Anpassen der Ergebnisse</h2>

<table class="simple-devider">
	<tr>
		<td>
			<h3>Kennungs-Nr.</h3>
		</td>
		<td>
			<div class="distinctly-input" style="width: 100%;">
				<input oninput="distinctlyInput(1)" type="text" maxlength="1" value="<?php echo $program_cache[0]; ?>" class="code-input" id="distinctlyInput1">
				<input oninput="distinctlyInput(2)" type="text" maxlength="1" value="<?php echo $program_cache[1]; ?>" class="code-input" id="distinctlyInput2">
				<input oninput="distinctlyInput(3)" type="text" maxlength="1" value="<?php echo $program_cache[2]; ?>" class="code-input" id="distinctlyInput3">
				<input oninput="distinctlyInput(4)" type="text" maxlength="1" value="<?php echo $program_cache[3]; ?>" class="code-input" id="distinctlyInput4">
				<input oninput="distinctlyInput(5)" type="text" maxlength="1" value="<?php echo $program_cache[4]; ?>" class="code-input" id="distinctlyInput5">
			</div>
		</td>
	</tr>
	<tr>
		<td>
			<h3>Sekundärbrücken abwählen</h3>
		</td>
		<td>
			<div class="program-field">
			
			
				
				
				<?php 
				
				$i = 0;
				
				$count = count($measurement_result);
				
				foreach ( $measurement_result as $bridge) { 
				
				
				?>
				
				<label class="checkbox-container">
					<input checked onchange="excludeBridge(<?php echo $count; ?>)" type="checkbox" id="programSelect_<?php echo $i; ?>" value='[<?php echo $bridge[0] . "," . $bridge[1];  ?>]'>
				
	
				<span class="checkbox-text">
						<?php echo $bridge[0] . "-" . $bridge[1];  ?>
					</span>
				</label>
				
				<?php
				
				$i++;
				
				} ?>
				
			</div>
		</td>
	</tr>
	<tr>
		<td colspan="2">
			<img id="result-editor-result" src="../stecker.php" />
		</td>
	</tr>
	
	
	<tr>
		<td>
			<h3>Besonderheiten</h3>
		</td>
		<td>
			<textarea id="database-special" style="height: 80px;" placeholder="z.B. + Brücke 45, - Brücke 13"></textarea>
		</td>
	</tr>
</table>

<hr />
<h2>Speichern unter...?</h2>

<div class="search-container">
	<input type="text" id="database-search-term" onkeyup="search('results')" placeholder="Beginnen Sie zu tippen..." />
	<div class="save-button" onclick="save('inventory','add');"><img src="/vendor/icons/floppy-disk.svg" \></div>
	<?php
	
	// Speichern für "action/inventory.php"
	$_SESSION["bridges"] = $measurement_result;
	
	?>
	<input type="hidden" id="database-bridges" value="<?php echo urlencode(json_encode($measurement_result)); ?>" />
	<input type="hidden" id="database-bridges-hidden" value="" />
	<div class="results"></div>
</div>
<p>
	<i>Die dargestellten Vorschläge befinden sich bereits in der Datenbank. Geben Sie einen Ort sein, der noch nicht in der Datenbank vorhanden ist, so wird dieser automatisch erstellt</i>
</p>

<hr />

<div class="save-button" onclick="if (window.confirm('Das Messergebnis wird verworfen, sollte es nicht gespeichert worden sein. Fortfahren?')) { window.location.href='#index'; pageload();$('.save-button').html('<img src=\'load.gif\' \>Bitte warten...');}"><img src="/vendor/icons/nav-arrow-left.svg" \>Zurück</div>


