<?php
	require_once("../conf.php");
/*
CREATE TABLE IF NOT EXISTS speech (
				token VARCHAR(20) PRIMARY KEY,
				msg VARCHAR(255),
				host VARCHAR(50),
				t TIMESTAMP DEFAULT now()
			)";
*/
	function speechRead($token) {
		global $sql;
		$query = "SELECT msg FROM speech WHERE token=$1";
		$data = $sql->sql_secure($query, array($token));
		$err = $sql->sql_error();
		return (!empty($err))? $err: $data[0]['msg'];
	}
	function speechUpsert($token, $msg) {
		global $sql;
		$query = "DELETE FROM speech WHERE EXTRACT(EPOCH FROM NOW()-t) > 36000"; 
		$sql->sql_query($query);
		$query = "INSERT INTO speech (token, msg, host) VALUES ($1, $2, '".($_SERVER['REMOTE_ADDR'].'_'.$_SERVER['HTTP_X_FORWARDED_FOR'])."') ON CONFLICT (token) DO UPDATE SET msg=$3";
		$data = $sql->sql_secure($query, array($token, $msg, $msg));
		$err = $sql->sql_error();
		if (!empty($err)) echo $err;
	}
	$sql = open_db();
	// if (!empty($_REQUEST['testupsert'])) {speechUpsert($_REQUEST['upsert'], $_REQUEST['msg']);exit();}
	// if (!empty($_REQUEST['testsread'])) {die(speechRead($_REQUEST['sread']));}
	$local = isset($_REQUEST['cdn'])? false: true; // true = use only locally installed modules, false = use cdn
	$lang = empty($_REQUEST['lang'])? 'it': substr($_REQUEST['lang'], 0, 2);
	$host = isset($hs[$_SERVER['REMOTE_ADDR']])? $hs[$_SERVER['REMOTE_ADDR']]: $_SERVER['REMOTE_ADDR'];
	function mylog() {
		file_put_contents('./logs'.date('Y').'.txt', date('Y-m-d H:i:s').' '.$_SERVER['REMOTE_ADDR'].'_'.$_SERVER['HTTP_X_FORWARDED_FOR'].' - '.$_SERVER['QUERY_STRING'].PHP_EOL , FILE_APPEND | LOCK_EX);
	}
	/*if (!empty($_REQUEST['init'])) {
		$t = $_REQUEST['init']-0;
		if ($t==0 || $t>1000000000000) die('');
		file_put_contents("./token", $t);
	}*/
	if (!empty($_REQUEST['search']) || !empty($_REQUEST['open'])) mylog();
	if (!empty($_REQUEST['list'])) {
		/*$t = file_get_contents("./token");
		if ($t != $_REQUEST['token']-0) die('[]');
		if (time() -filectime("./token") > 36000) die('{}');*/
		$query = "SELECT id FROM launcher WHERE $1=ANY(speech_$lang)";
		$data = $sql->sql_secure($query, array($_REQUEST['list']));
		if ($data !== false) {
			$query = "SELECT title FROM launcher WHERE folder_id=".$data[0]['id'];
			$data = $sql->sql_query($query);
			die(json_encode($data));
		}
		else {
			$query = "SELECT id, title, description, word_similarity(title, $1) AS ws FROM launcher ORDER BY ws DESC LIMIT 3";
			if (isset($_REQUEST['debug'])) echo "$query;<br>";
			$data = $sql->sql_secure($query, array($_REQUEST['list']));
			if ($data !== false && $data[0]['ws'] > 2.0*$data[1]['ws'])  {
				$query = "SELECT title FROM launcher WHERE folder_id=".$data[0]['id'];
				$data = $sql->sql_query($query);
				die(json_encode($data));
			}
			die(json_encode($data));
		}
	}
	if (!empty($_REQUEST['open'])) {
		/*
		pwma=# CREATE EXTENSION pg_trgm;
		pub_types              │ character varying(2000)[]
		SELECT * FROM mytable WHERE 'give'=ANY(speech_it);
		UPDATE launcher SET speech_it = array_append(speech_it, $1) WHERE id = $2
		
		https://puma-01.elettra.eu/lib/fm.php?open_editor=/run/knob/launch_do
		
		nokill
		100 100 /runtime/bin/modmulti-gui
		
		*/
		if (!empty($_REQUEST['speech'])) {
			if (!empty($_REQUEST['id'])) {
				$query = "UPDATE launcher SET speech_$lang = array_append(speech_$lang, $1) WHERE id = $2";
				$data = $sql->sql_secure($query, array($_REQUEST['speech'],$_REQUEST['id']));
			}
			else {
				$query = "UPDATE launcher SET speech_$lang = array_append(speech_$lang, $1) WHERE exename = $2";
				$data = $sql->sql_secure($query, array($_REQUEST['speech'],$_REQUEST['open']));
			}
			// header('Content-Type: application/json');
			// die(json_encode($data));
		}
		// $t = file_get_contents("./token"); if ($t != $_REQUEST['token']-0) die('[]'); if (time() -filectime("./token") > 36000) die('{}');
		$query = "SELECT exename, path FROM launcher WHERE $1=ANY(speech_$lang)";
		$data = $sql->sql_secure($query, array($_REQUEST['open']));
		$host = $_REQUEST['host'];
		if (isset($_REQUEST['debug'])) echo "$query; \$1: {$_REQUEST['open']}<br>../../knob/launcher.php?open={$data[0]["path"]}{$data[0]["exename"]}&host=$host";
		if ($data !== false) {$d = file_get_contents("http://puma-01.elettra.eu/knob/launcher.php?open={$data[0]["path"]}{$data[0]["exename"]}&host=$host"); die(json_encode($d));}
		// die("$query<br>$err<br>\n".json_encode($data));
		$query = "SELECT id, title, description, exename, path, word_similarity(title, $1) AS ws FROM launcher ORDER BY ws DESC LIMIT 3";
		$data = $sql->sql_secure($query, array($_REQUEST['open']));
		if (isset($_REQUEST['debug'])) echo "$query;<br>".json_encode($data);
		if ($data !== false && $data[0]['ws'] > 2.0*$data[1]['ws'] && $data[1]['ws']>0.1) {$d = file_get_contents("http://puma-01.elettra.eu/knob/launcher.php?open={$data[0]["path"]}{$data[0]["exename"]}&host=$host"); die(json_encode($d));}
		$err = $sql->sql_error();
		header('Content-Type: application/json');
		die(json_encode($data));
	}
	if (!empty($_REQUEST['search'])) {
		if (!empty($_REQUEST['speech'])) {
			$speech = explode('_', strtr(strtoupper($_REQUEST['speech']), [' '=>'_', '.'=>'_', '-'=>'_']));
			$sr = explode('_', $_REQUEST['search']);
			foreach ($speech as $i=>$s) {
				if ($s != $sr[$i]) {
					$query = "INSERT INTO speechreplace (speech, replace, lang) VALUES ($1, $2, $3)";
					$data = $sql->sql_secure($query, array($s, $sr[$i], $lang));
				}
			}
		}
		$query = "SELECT speech, replace FROM speechreplace WHERE lang=$1";
		$data = $sql->sql_secure($query, array($lang));
		$replace = [];
		foreach ($data as $d) {
			$replace[$d['speech']] = $d['replace'];
		}
		$search = strtr($_REQUEST['search'], $replace);
		if (!empty($search)) {
			speechUpsert($_REQUEST['token'], $search);
			for ($i=0; $i<50; $i++) {
				$f = speechRead($_REQUEST['token']);
				if (!empty($f) && $f != $search) {
					speechUpsert($_REQUEST['token'], '');
					die($f);
				}
				usleep(100000);
			}
			speechUpsert($_REQUEST['token'], '');
			die("$search not found, timeout");
		}
	}
	if (isset($_REQUEST['readresult'])) {
		speechUpsert($_REQUEST['token'], substr($_REQUEST['readresult'], 0, 15));
	}
	if (isset($_REQUEST['read'])) {
		set_time_limit(0);
		while (true) {
			$f = speechRead($_REQUEST['token']);
			if (!empty($f)) {
				speechUpsert($_REQUEST['token'], '');
				die($f);
			}
			usleep(100000);
		}
	}
	function makeQuery($id, $e) {
		$path = strtr($e->attributes()->path.'/', array('//'=>'/'));
		return strtr("INSERT INTO launcher (folder_id, title, description, exename, path) VALUES ($id, \"".$e->title.'","'.$e->description.'","'.$e->attributes()->exename."\",\"$path\")", ['""'=>'NULL','"/"'=>'NULL',"'"=>'','"'=>"'"]);
	}
	function elementArray($id, $element) {
		global $sql;
		foreach ($element as $e) {
			$query = makeQuery($id, $e);
			echo "$query;<br>\n";
			$sql->sql_query($query);
		}
	}
	function folderArray($id, $folder) {
		global $sql;
		foreach ($folder as $i=>$e) {
			$query = makeQuery($id, $e);
			echo "$query;<br>\n";
			$sql->sql_query($query);
			$lastid = $sql->last_insert_id() - 0;
			if (isset($e->folder)) folderArray($lastid, $e->folder);
			if (isset($e->element)) elementArray($lastid, $e->element);
		}
	}
	if (isset($_REQUEST['starter'])) {
		// ALTER SEQUENCE launcher_id_seq RESTART WITH 6
		/*$sql->sql_query("INSERT INTO launcher (folder_id, title, description, exename) VALUES (2, 'Jive','Jive','jive')");
		echo $sql->last_insert_id();
		die();
		puma@pwma-dev:~$ sudo psql -U postgres
		postgres=# \c pwma
		*/
		
		$context = stream_context_create(array("ssl"=>array("verify_peer"=>false,"verify_peer_name"=>false)));
		// /home/fermi/etc/launcher/fermi/launcher_es.conf
		// /runtime/etc/browser/fermi.xml
		// /runtime/etc/browser/laser.xml
		if ($_REQUEST['starter'] == 'launcher_es.conf') {
			// DELETE FROM launcher WHERE id > 2094
			// ALTER SEQUENCE launcher_id_seq RESTART WITH 2095
			$f = file($_REQUEST['starter']);
			$j == -10;
			foreach ($f as $i=>$d) {
				if (strpos($d, '#')===0) continue;
				if (strpos($d, '@HEADING')===0) {
					if (strpos($f[$i+1],'Injector')===0) $lastid = 197;
					else if (strpos($f[$i+1], 'FEL1')===0) $lastid = 1335;
					else if (strpos($f[$i+1], 'FEL2')===0) $lastid = 1637;
					else if (strpos($f[$i+1], 'Tools-2')===0) continue;
					else if (strpos($f[$i+1], 'Legenda')===0) break;
					else {$query = "INSERT INTO launcher (folder_id, title) VALUES (1, \"".trim($f[$i+1])."\")";echo "$query<br>\n"; $sql->sql_query($query); $lastid = $sql->last_insert_id() - 0;}
					continue;
				}
				if (strpos($d, '@')===0 && strpos($d, 'TOOL')===2) $j = $i;
				if ($i==$j+1) $title = $d;
				if ($i==$j+2) {$exename = $d; if (strpos($d, '/')===0) {$exename = basename($d); $path = dirname($d);} else $path = '';}
				if ($i==$j+4) {
					$query = strtr("INSERT INTO launcher (folder_id, title, description, exename, path) VALUES ($lastid, \"$title\",\"$d\",\"$exename\",\"$path\")", ['""'=>'NULL','"/"'=>'NULL',"'"=>'','"'=>"'"]);
					$sql->sql_query($query);
					echo "$query<br>\n";
				}
				// echo "$d<br>\n";
			}
			die('done');
		}
		$f = strtr(file_get_contents("https://gitlab.elettra.eu/cs/etc/browser/fermi/-/raw/master/fermi.xml", false, $context), ['exename=""'=>'']);
		// var_dump(libxml_use_internal_errors(true));
		$xml = simplexml_load_string($f, "SimpleXMLElement", LIBXML_NOERROR |  LIBXML_ERR_NONE);
		if ($xml === false) {
			echo "Failed loading XML\n";
			foreach(libxml_get_errors() as $error) {
				echo "\t", $error->message;
			}
		}
		// elementArray(1, $xml->folder->element);
		folderArray(1, $xml->folder->folder);
		echo "<pre>";
		print_r($xml);
		die('</pre>');
	}
	$query = "SELECT id, title FROM launcher WHERE exename IS NOT NULL AND id>$1";
	$data = $sql->sql_secure($query, [5]);
	$launcher = [];
	foreach ($data as $d) $launcher[] = $d['title'];
?>

<!doctype html>
<html lang="en">
	<head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<title>CS Talk</title>
		<link rel="stylesheet" href="<?php echo ($local? '../../lib/jquery/jquery-ui.min.css': 'https://code.jquery.com/ui/1.13.3/themes/base/jquery-ui.css');?>">
		<script src="<?php echo ($local? '../../lib/jquery/jquery.min.js': 'https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js');?>" type="text/javascript"></script>
		<script src="<?php echo ($local? '../../lib/jquery/jquery-ui.min.js': 'https://cdn.jsdelivr.net/npm/jquery-ui@1.13.3/dist/jquery-ui.min.js');?>" type="text/javascript"></script>
		<link rel="stylesheet" href="../../lib/bootstrap4/bootstrap.min.css">
		<script src="../../lib/bootstrap4/bootstrap.bundle.min.js"></script>
		<script src="./talk.js"></script>
	</head>
	<body onLoad='myload()'>
		<div id='transcriptDiv' style='display:none;'></div>
		<div style="max-width: 280px; max-height: 30px; text-align: center;">
			<audio id='speechText' onended='speakagain();' onerror='showLog("audio err: "+event.error)'></audio>
			<span style='color: darkgreen; font-weight: bold;' id='title'>Talk to ...</span>

			<img src='./microphone-na.png' onClick='naClick()' title='not available' id='micna'>
			<img src='./microphone-on.png' onClick='stopRec()' id='micstart' style='display: none; padding-right: 60px; max-width: 300px;'>
			<img src='./microphone-off.png' onClick='startRec()' id='micstop' style='display: none; padding-right: 60px;'>
			<div style='cursor: pointer;padding-right: 5px; text-align: right; margin-top: -1.3em;' id='langselect'>
				<img style="max-height: 18px; margin-right: 10px;" src='./it-IT.png' onClick="switchLocale('it')">
				<img style="max-height: 18px; margin-right: 10px;" src='./en-US.png' onClick="switchLocale('en')">
				<span style='color: darkgreen; font-weight: bold;' onClick='commandlistinfo()'> ? </span>
			</div>
			<div style='padding-left: 5px; text-align: left; margin-top: -1.3em;' id='operation'>
				<img style="margin-right: 10px;" id='open' src='./open.png'>
				<img style="margin-right: 10px;" id='search' src='./search.png'>&nbsp;
			</div>
			<span style='color: darkblue; font-weight: bold;' id='miclabel'>comandi vocali&nbsp;&nbsp;&nbsp;</span>
			<table id ='openTable' class="table table-hover"></table>
			<pre id='log'></pre>
			<script>
				// showLog('webkitSpeechRecognition: '+ typeof window.webkitSpeechRecognition);
				// showLog('SpeechRecognition: '+ typeof window.SpeechRecognition);
				window.SpeechRecognition = window.webkitSpeechRecognition || window.SpeechRecognition;
				if (typeof window.SpeechRecognition == 'undefined' && document.location.search.indexOf('?d=')==-1) {
					let tok = document.location.search.indexOf('token=')==-1? Math.round(Math.random()*1000000000000+1): document.location.search.split('token=')[1].split('&')[0];
					if (isNaN(tok) || tok<1000000000) tok = Math.round(Math.random()*1000000000000+1);
					console.log('./qr.php?data='+tok+'&host=<?php echo $host;?>');
					// fetch('./talk.php?init='+tok+'&host=<?php echo $host;?>');
					document.getElementById('micstart').src = './qr.php?data='+tok+'&host=<?php echo $host;?>';
					document.getElementById('langselect').style.display = 'none';
					document.getElementById('miclabel').style.display = 'none';
					$('#search').hide(); $('#open').hide();
					if (window.parent && window.parent.document.getElementById('talk')) window.parent.document.getElementById('talk').style.height = '20px';
				}
				const launcher = ["<?php echo implode('","', $launcher);?>"];
			</script>
		</div>
	</body>
</html>