<?php
class App{
	function debug($var,$append=false){ob_start();var_dump($var);file_put_contents('appdebug.txt',ob_get_contents(),$append?FILE_APPEND:0);ob_end_clean();}
	function userlog(){file_put_contents("{$this->froot}/main/app/userlogs.csv",date('H:i d M Y').", {$this->user['user']}, {$_SERVER['REMOTE_ADDR']}, {$_SERVER['REQUEST_URI']}\n",FILE_APPEND);}
	function mkdir($dir){if (!file_exists($dir)){$mask=umask(0);mkdir($dir,0777,true);umask($mask);}}
	function getPost($key){return isset($_POST[$key])?$_POST[$key]:false;}
	function nopage($message){$this->heads('No Access');$this->header();echo "<section><article><h1>No Access</h1><p class='center'>$message</p></article></section>";$this->footer();$this->tails();}
	function privileged($usertype){return (($this->user!==false)&&($this->usertypes[$this->user['type']]<=$this->usertypes[$usertype]));}
	function creditWorthy($mincreds=50){return (($this->user!==false)&&($this->user['cred']>=$mincreds));}
	function setCookie($k,$v){setcookie($k,$v,time()+3600*24*30,$this->cookiePath.'; samesite=strict',$_SERVER['SERVER_NAME'],false,true);$_COOKIE[$k]=$v;}
	function clearCookie($k){setcookie($k,'',time()-3600*24*30,$this->cookiePath.'; samesite=strict',$_SERVER['SERVER_NAME'],false,true);unset($_COOKIE[$k]);}
	function memoryDisclosure($id){echo "id='$id' ontoggle=\"localStorage.setItem('$id',this.open);\"";}
	function setMemoryDisclosures(...$args){$out="<script>function setMemoryDisclosures(...args){args.forEach(item=>{document.getElementById(item).open=localStorage.getItem(item)=='true';});}setMemoryDisclosures(";forEach($args as $arg)$out.="'$arg',";$out=substr($out,0,strlen($out)-1);$out.=");</script>\n";echo $out;}
	function addScript($script,$async=false){$async=$async?'async':'';$this->scriptHTML.="<script type='text/javascript' src='$script' $async></script>";}
	function addStyle($style){$this->styleHTML.="<link rel='stylesheet' type='text/css' href='$style' />";}

	function chainScript($name,$func){
		echo "<script>
			var $name=document.body.onload;
			document.body.onload=(e,args)=>{
				{$name}(e,args);
				$func
			}
		</script>";
	}
	function chainElement($name,$style='',...$args){
		$ucname=ucfirst($name);
		$jsonargs=json_encode($args);
		echo "<div id='$name' style='$style'></div>";
		$this->chainScript(
			"{$name}Chain",
			"$name=new $ucname('$name','{$this->wroot}','{$this->user['user']}',$jsonargs);"
		);
	}
	function windowChain($name,...$args){
		$ucname=ucfirst($name);
		$argsjson=json_encode($args);
		echo "\n<script>
		var {$name}Chain=window.onload;
		window.onload=()=>{
			if ({$name}Chain)
				{$name}Chain();
				{$name}=new {$ucname}($argsjson);
		}
		</script>";
	}


	function readableNumber($n){if(!$n)$n=0;$r=strrev(implode(',',str_split(strrev($n),3)));return $r===''?'0':$r;}
	function link($label,$url,$target='_top'){echo "<a href='{$this->wroot}$url' target='$target'>$label</a>";}
	function droid($label,$uri,$img=null,$fg=null){
		echo "<span class='droid'><a class='droid' style='";
		if ($fg) echo "color:$fg;";
		if ($img) echo "background:url({$img}) 50%; background-size:contain;";
		echo "' href='{$uri}'>$label</a></span>";
	}
	function indexLink(){
		echo "<a href='".pathinfo($_SERVER['PHP_SELF'],PATHINFO_DIRNAME)."'>Section Index</a><br/>";
	}
	function indexer(){
		echo "<div class='left'>";
		$files=glob($_SERVER['DOCUMENT_ROOT'].pathinfo($_SERVER['PHP_SELF'],PATHINFO_DIRNAME).'/*.php');
		usort($files,function($a,$b){$infoA=stat($a);$infoB=stat($b);return $infoB['ctime']-$infoA['ctime'];});
		if (sizeof($files)<2) echo "<h6>OMG, you guys, I'm soooo busy... literally. This section is still in the works. Bear with me, 'kay?</h6>";
		foreach($files as $f){
			$f=substr($f,1+strrpos($f,'/'));
			if ($f=='index.php') continue;
			$f=substr($f,0,-4);
			$x='';
			for ($i=0;$i<strlen($f);$i++){
				if (($i>0)&&(($f[$i-1]<'A')||($f[$i-1]>'Z'))&&($f[$i]>='A')&&($f[$i]<='Z')) $x.=' ';
				$x.=$f[$i];
			}
			$path=pathinfo($_SERVER['PHP_SELF'],PATHINFO_DIRNAME);
			$img=$path.substr($path,strrpos($path,'/')).'.png';
			$this->droid($x,"$path/$f.php",$img);
		}
		echo "</div>";
	}
	function globalIndexer($dirs){
		echo "<div class='left' style='height:33vh;overflow:scroll'>";
		$files=[];
		foreach($dirs as $dir) $files=array_merge($files,glob("{$this->froot}/$dir/*.php"));
		usort($files,function($a,$b){$infoA=stat($a);$infoB=stat($b);return $infoB['ctime']-$infoA['ctime'];});
		foreach($files as $f){
			$path=substr($f,strlen($_SERVER['DOCUMENT_ROOT']));
			$path=substr($path,0,strrpos($path,'/'));
			$f=substr($f,1+strrpos($f,'/'));
			if ($f=='index.php') continue;
			$f=substr($f,0,-4);
			$x='';
			for ($i=0;$i<strlen($f);$i++){
				if (($i>0)&&(($f[$i-1]<'A')||($f[$i-1]>'Z'))&&($f[$i]>='A')&&($f[$i]<='Z')) $x.=' ';
				$x.=$f[$i];
			}
			$img=$path.substr($path,strrpos($path,'/')).'.png';
			$this->droid($x,"$path/$f.php",$img);
		}
		echo "</div>";
	}










	function heads($title='',$keywords='',$description='Webpage from Auranos.org',$author='Stephen Duffy'){
		echo "<!doctype html><html lang='en-gb'><head><meta charset='utf-8' /><meta name='viewport' content='width=device-width, initial-scale=1.0' />";
		echo "\n<title>auranos $title</title>\n<meta name='author' content=$author />\n<meta name='keywords' content='$keywords' />\n<meta name='description' content='$description' />";
		if (file_exists("{$this->froot}/main/assets/favicon/iconmeta.htm")) echo file_get_contents("{$this->froot}/main/assets/favicon/iconmeta.htm");
		echo "\n{$this->scriptHTML}\n{$this->styleHTML}";
		if (isset($_COOKIE['theme']))echo "\n<meta http-equiv='Default-Style' id='themeSheet' content=".$_COOKIE['theme']." />";
		else echo "\n<meta http-equiv='Default-Style' id='themeSheet' content='Lite' />";
		echo "\n<link rel='stylesheet' type='text/css' class='themeSheet' title='Lite' href='{$this->wroot}/main/app/lite.css?v={$this->ver}' />";
		echo "\n<link rel='stylesheet' type='text/css' class='themeSheet' title='Dark' href='{$this->wroot}/main/app/dark.css?v={$this->ver}' />";
		$this->windowChain('app',"{$this->wroot}");
		echo "\n</head><body>\n";
	}
	function tails(){echo "\n</body></html>";}





	function logout(){
		$this->clearCookie('uid');$this->clearCookie('hid');$this->user=false;
		session_start();unset($_SESSION['user']);session_write_close();
		Header("Location: {$_SERVER['REQUEST_URI']}");
	}
	function login($user,$pass){
		if ($this->user=$this->findUser($user)){
			$hash=$this->user['hash'];
			if (password_verify($pass,$hash)){
				$this->setCookie('uid',$this->user['uuid']);$this->setCookie('hid',md5($this->user['hash']));
				if ($this->user){$this->userlog();session_start();$_SESSION['user']=$this->user['user'];session_write_close();}
				return $this->user;
			}
		}
		return false;
	}
	function cookieLogin(){
		if ((!isset($_COOKIE['uid'])||!isset($_COOKIE['hid']))) return false;
		$uid=$_COOKIE['uid'];$hid=$_COOKIE['hid'];
		$response=$this->db->query("select * from users where uuid='$uid';");
		if ($response->num_rows==0) return false;
		$this->test=$response->fetch_assoc();
		if ($hid!==md5($this->test['hash'])) return false;
		$this->user=$this->test;unset($this->test);
		if ($this->user){$this->userlog();session_start();$_SESSION['user']=$this->user['user'];session_write_close();}
		return $this->user;
	}





	function dbInit($config){
		mysqli_report(MYSQLI_REPORT_ERROR|MYSQLI_REPORT_STRICT);
		try{$this->db=new mysqli($config['dbHost'],$config['dbUser'],$config['dbPass'],$config['dbName'],$config['dbPort']);}
		catch (Exception $exception){return false;};
		return ($this->db->connect_errno===0);
	}
	function findUser($username){
		$response=$this->db->query("select * from users where user='$username';");
		if ($response->num_rows==0) return false;
		return $response->fetch_assoc();
	}
	function getUser($uuid){
		$response=$this->db->query("select * from users where uuid='$uuid';");
		if ($response->num_rows==0) return false;
		return $response->fetch_assoc();
	}
	function createUserTable(){
		try{
			$this->db->query("create table users(
				uuid int not null primary key auto_increment,
				date timestamp default current_timestamp,
				type varchar(32),
				user varchar(64) unique,
				hash varchar(256),
				cred int
			);");
		} catch (Exception $ex){return false;}
		return true;
	}
	function addUser($type,$user,$hash,$avatar=null){
		if ($this->findUser($user)) return false;
		$this->db->query("insert into users(type,user,hash,cred) values('$type','$user','$hash',50);");
		if ($this->db->errno!==0) return false;
		if (!file_exists("{$this->froot}/main/users/$user")) $this->mkdir("{$this->froot}/main/users/$user",0777,true);
		if (!$avatar) $avatar="{$this->froot}/main/assets/anonymous.png";
		copy($avatar,"{$this->froot}/main/users/$user/avatar.png");
		return true;
	}
	function delUser($uuid){
		if ($uuid<1) return false;
		$u=$this->getUser($uuid)['user'];
		$this->db->query("delete from users where uuid='$uuid';");
		if (!$this->db->errno) system("rm -rf ".escapeshellarg("{$this->froot}/main/users/$u"));
		else return false;
	}
	function editUser($uuid,$fields){ //fields is an array of [key=>$value,$key=>value,...]
		$q='';foreach($fields as $key=>$value) $q.="$key='$value',";
		if ($q!='') $q=substr($q,0,-1);	
		$q="update users set $q where uuid='$uuid';";
		$this->db->query($q);
		if ($this->db->errno!==0) return false;
		return true;
	}
	function getUsers(){
		$response=$this->db->query("select * from users;");
		if ($response->num_rows==0) return false;
		else{
			$ra=[];
			while($row=$response->fetch_assoc()) array_push($ra,$row);
			return $ra;
		}
	}





	function imageGDCreate($file,$ext=false){$img=null;if (!$ext) $ext=substr($file,strrpos($file,'.'));
		switch($ext){
			case '.png':$img=imagecreatefrompng("$file"); break;
			case '.jpg':$img=imagecreatefromjpeg("$file"); break;
			case '.jpeg':$img=imagecreatefromjpeg("$file"); break;
			case '.gif':$img=imagecreatefromgif("$file"); break;
			case '.bmp':$img=imagecreatefrombmp("$file"); break;
			case '.webp':$img=imagecreatefromwebp("$file"); break;
		}
		return $img;
	}
	function imageGDSquare($img,$size=512){
		if ( imagesx($img) > imagesy($img) ) $i0=imagescale($img,$size,-1,IMG_BICUBIC_FIXED);
		else $i0=imagescale($img,$size*(imagesx($img)/imagesy($img)),$size,IMG_BICUBIC_FIXED);
		imagedestroy($img);$img=imagecreatetruecolor($size,$size);imageSaveAlpha($img,true);
		imagefill($img,$size>>1,$size>>1,imagecolorallocatealpha($img,0,0,0,127));
		imagecopy($img,$i0,($size-imagesx($i0))/2,($size-imagesy($i0))/2,0,0,imagesx($i0),imagesy($i0));
		imagedestroy($i0);return $img;
	}
	function imageCatcher($name,$uri){if (($this->getPost("{$name}Submit"))&&($_FILES[$name])){$ext=$_FILES[$name]['name'];$ext=substr($ext,strrpos($ext,'.'));$img=$this->imageGDCreate($_FILES[$name]['tmp_name'],$ext);if ($img){$this->mkdir(dirname("{$this->froot}$uri"));$img=$this->imageGDSquare($img,512);imagepng($img,"{$this->froot}$uri");imagedestroy($img);}}}
	function imageCatchlet($name){if (!isset($_FILES[$name]))return false;else{$ext=$_FILES[$name]['name'];$ext=substr($ext,strrpos($ext,'.'));$img=$this->imageGDCreate($_FILES[$name]['tmp_name'],$ext);if ($img) return $this->imageGDSquare($img,512);}}
	function imageDropper($name,$uri=null){$now=microtime(true);if (!file_exists($this->froot.$uri)) $uri='/main/assets/icons/anonymous.png';echo "<form class='tall' method='post' enctype='multipart/form-data'><input name='$name' style='background-image:url({$this->wroot}$uri?v=$now)' type='file' class='imageDrop' onchange='app.thumbChange(this);' ondragover='app.thumbDragover(this,event);' ondrop='app.thumbDrop(this,event);' /><input type='submit' value='Use This Image' name='{$name}Submit' /></form>";}
	function imageDroplet($name){echo "<input type='file' name='$name' class='imageDrop' onchange='app.thumbChange(this);' ondragover='app.thumbDragover(this,event);' ondrop='app.thumbDrop(this,event);' style='background-image:url({$this->wroot}/main/assets/icons/anonymous.png)' />";}





	function sidebarLink($label,$url,$target='_top'){echo "<a href='$url' target='$target'>$label</a>";}
	function sidebarForm($title,$args){
				echo "<p>$title</p>";
				echo "<form class='sidebar' method='post'>";
				forEach($args as $arg) echo "<input type='{$arg[2]}' name='{$arg[1]}' placeholder='{$arg[0]}' value='{$arg[3]}' />";
				echo "</form>";
	}
	function sidebar(){
		echo "<img onclick='app.toggleSidebar(this.nextSibling);' class='hamburger' src='{$this->wroot}/main/assets/icons/hamburger.png' />";
		$sbstatus='0px';if (isset($_COOKIE['sidebar'])&&($_COOKIE['sidebar'])) $sbstatus='var(--sideroom);';
		echo "<div class='sidebar' style='width:$sbstatus;'>";
		echo "<article class='login'>";
			if ($this->user===false){
				$this->sidebarLink("Join","{$this->wroot}/main/special/join.php");
				if (in_array('googleAPI',$this->plugins)){echo "<a style='cursor:pointer;font-size:1.125rem;' onclick='googleAPI=new GoogleAPI([\"{$this->pluginsConfig['googleAPI']->client_id}\"]);return false;'>Login with Google</a>";}
				if (in_array('facebookAPI',$this->plugins)){echo "<a style='cursor:pointer;font-size:1.125rem;' onclick='facebookAPI=new FacebookAPI([\"{$this->pluginsConfig['facebookAPI']->client_id}\"]);return false;'>Login with Facebook</a>";}
				$this->sidebarForm("Login with username and password",[
					['username','lu','text'],
					['password','lp','password'],
					['li','cmd','hidden','li'],
					['login','lis','submit','login']
				]);
			}
			else{
				$this->sidebarLink("Dashboard","{$this->wroot}/main/special/account.php");
				$this->sidebarForm("Logged in as [{$this->user['user']}]",[
					['lo','cmd','hidden','lo'],
					['logout','los','submit','logout']
				]);
			}
		echo "</article>";
		if ($this->privileged('superadmin')){
			$this->sidebarLink("Setup","{$this->wroot}/main/special/setup.php");
		}
		if ($this->privileged('staff')){
			$this->sidebarLink("Users","{$this->wroot}/main/special/users.php");
		}
		$this->sidebarLink("Privacy","{$this->wroot}/main/special/privacy.php");
		$this->sidebarLink("Contact","{$this->wroot}/main/special/contact.php");
		$this->sidebarLink("Copyright","{$this->wroot}/main/special/copyright.php");
		echo "</div>";
	}
	function headMenu($label,$items,$popup){
		echo "<details class='menu' title='$popup'><summary>$label</summary>";
		foreach($items as $item) echo "<a title='{$item[2]}' href='{$this->wroot}{$item[1]}'>{$item[0]}</a>";
		echo "</details>";
	}
	function header(){
		echo "<header id='header'>";
		$this->sidebar();
		echo "<img class='headicon' onclick='app.toggleTheme();' src='{$this->wroot}/main/assets/icons/lights.png' />";
		echo "<a class='logo' href='{$this->wroot}/'>auranos</a>";
		$this->headMenu('Sections',[
			['The Politburo',"/ThePolitburo",'The Ministry of BS'],
			['The Despair Desk',"/TheDespairDesk",'Tessa Flows into Your Life (Uninvited)'],
			['Celebrity Sparkle',"/CelebritySparkle","Tessa's Tabloid Tales"],
			['The Sports Siren',"/TheSportsSiren",'Trash talk from a benchwarmer'],
			['Gadget Grumbles',"/GadgetGrumbles",'Tessa Takes on the Titans'],
		],'Special Interest Sections');
		echo "</header>";
		echo "<main>";
	}
	function footer(){
		echo "</main>";
		echo "<br/>";
		echo "<footer class='center'>";
		echo "<a class='foot' href='{$this->wroot}/main/special/copyright.php'>&copy;<p style='display:inline;'>auranos.org</p>&copy;</a>";
		echo "</footer>";
	}





	function __construct($wroot){
		$this->ver=0;
		$this->usertypes=['superadmin'=>0,'admin'=>1,'staff'=>2,'affiliate'=>3,'associate'=>4,'social'=>5,'public'=>6];
		$this->wroot=$wroot;$this->froot=$_SERVER['DOCUMENT_ROOT'].$wroot;$this->fqwroot='http'.(isset($_SERVER["HTTPS"])?'s':'').'://'.$_SERVER['SERVER_NAME'].$this->wroot;
		$this->styleHTML='';$this->scriptHTML='';$this->cookiePath=$this->wroot?$this->wroot:'/';
		$this->temp="/main/temp";$this->user=false;$cfgRequired=false;
		if (!file_exists("{$this->froot}/main/app/config.json"))$cfgRequired=true;
		else{
			$this->config=json_decode(file_get_contents("{$this->froot}/main/app/config.json"),true);
			if (!$this->dbInit($this->config))$cfgRequired=true;
			else{
				//plugins are special modules used within app.php itself and kept in the special plugins folder
				$this->plugins=json_decode(file_get_contents("{$this->froot}/main/app/plugins.json"));
				$this->user=$this->cookieLogin();
				if ($cmd=$this->getPost('cmd')) switch($cmd){
					case 'li':$this->user=$this->login($this->getPost('lu'),$this->getPost('lp'));break;
					case 'lo':$this->logout();break;
					case 'imageDrop':{
						$filename=uniqid("{$this->temp}/temp-");
						$ext=pathinfo($_FILES['image']['name'],PATHINFO_EXTENSION);
						move_uploaded_file($_FILES['image']['tmp_name'],"{$this->froot}{$filename}.$ext");
						echo "$filename.$ext";
						exit;
					}
					break;
				}
			} 
		}
		if (($cfgRequired)&&($_SERVER['SCRIPT_NAME']!=="{$this->wroot}/main/special/setup.php")) header("Location: {$this->wroot}/main/special/setup.php");
		$this->addStyle("{$this->wroot}/main/app/global.css");
		$this->addStyle("{$this->wroot}/main/app/App.css");
		$this->addScript("{$this->wroot}/main/app/App.js");
		foreach($this->plugins as $plugin){
			$ucplugin=ucfirst($plugin);
			$this->pluginsConfig[$plugin]=json_decode(file_get_contents("{$this->froot}/main/plugins/$plugin/config.json"));
			$this->addScript("{$this->wroot}/main/plugins/$plugin/$ucplugin.js");
		}
	}
}
$app=new App($wroot);
?>