<?php



//Déclaration d'un item de menu dans le menu principal
function host_menu(&$menuItems){
	global $myUser;
	if(!$myUser->can('host','read')) return;
	$menuItems[] = array(
		'sort'=>3,
		'url'=>'index.php?module=host',
		'label'=>'Hébergement',
		'icon'=> 'fab fa-ubuntu',
		'color'=> '#d35400'
	);
}

//Cette fonction va generer une page quand on clique sur Hébergement dans menu
function host_page(){
	global $_;
	if(!isset($_['module']) || $_['module'] !='host') return;
	$page = !isset($_['page']) ? 'list.machine' : $_['page'];
	$page = str_replace('..','',$page);
	$file = __DIR__.SLASH.'page.'.$page.'.php';
	if(!file_exists($file)) throw new Exception("Page ".$page." inexistante");

	require_once($file);
}

//Fonction executée lors de l'activation du plugin
function host_install($id){
	if($id != 'fr.core.host') return;
	Entity::install(__DIR__);

	$dictionary = new Dictionary();
    	$dictionary->slug = 'host_machine_os';
    	if(Dictionary::rowCount(array('slug'=>$dictionary->slug)) ==0){
	    	$dictionary->label = 'Machine / Environnement : Système d\'exploitation';
	    	$dictionary->parent = 0;
	    	$dictionary->state = Dictionary::ACTIVE;
	    	$dictionary->save();

	    	foreach(array(
	    		'other'=>'Autre',
	    		'linux_ubuntu'=>'Linux - Ubuntu 12.4',
	    		'linux_ubuntu'=>'Linux - Ubuntu 14.4',
	    		'linux_ubuntu'=>'Linux - Ubuntu 16.4',
	    		'linux_ubuntu'=>'Linux - Ubuntu 18.4',
	    		'linux_ubuntu'=>'Linux - Ubuntu 20.4',
	    		'linux_ubuntu'=>'Linux - Ubuntu 22.4',
	    		'window'=>'Windows server',
	    	) as $key=>$value){
		    	$item = new Dictionary();
				$item->slug = 'host_machine_os_'.$key;
				$item->label = $value;
				$item->parent = $dictionary->id;
				$item->state = Dictionary::ACTIVE;
				$item->save();
			}
	    }

}

//Fonction executée lors de la désactivation du plugin
function host_uninstall($id){
	if($id != 'fr.core.host') return;
	Entity::uninstall(__DIR__);
	$dictionary = Dictionary::bySlug('host_machine_os');
    	if($dictionary!= false && $dictionary->id!=0){
    		Dictionary::delete(array('parent'=>$dictionary->id));
    		Dictionary::delete(array('id'=>$dictionary->id));
    	}

}

//Déclaration des sections de droits du plugin

Right::register("host",array('label'=>"Gestion des droits sur le plugin Hébergement"));


//cette fonction comprends toutes les actions du plugin qui ne nécessitent pas de vue html
function host_action(){
	require_once(__DIR__.SLASH.'action.php');
}
//Déclaration du menu de réglages
function host_menu_setting(&$settingMenu){
	global $myUser;

	if(!$myUser->can('host','configure')) return;
	$settingMenu[]= array(
		'sort' =>1,
		'url' => 'setting.php?section=global.host',
		'icon' => 'fas fa-angle-right',
		'label' => 'Hébergement'
	);
}

//Déclaration des pages de réglages
function host_content_setting(){
	global $_;
	if(file_exists(__DIR__.SLASH.'setting.'.$_['section'].'.php'))
		require_once(__DIR__.SLASH.'setting.'.$_['section'].'.php');
}


require_once(__DIR__.SLASH.'action.php');


function host_ping_url($url){
	$response = array();
	try{

		if(!preg_match('/^https?:\/\//im', $url)) $url = 'http://'.$url;

		$request = @get_headers($url, true);

		$response['code'] = 500;
		$response['message'] = 'Erreur inconnue';

		if(!$request){
			$response['code'] = 500;
			$response['message'] = 'Impossible de requeter l\'url';
			return $response;
		}

		if(is_array($request) && isset($request[0])){

			$headers = array();
			// Make more sane response
		    foreach($request as $h => $v) {
		        if(is_int($h)){
		            $headers[$h]['Status'] = $v;
		        } else {
		            if(is_string($v)) $headers[0][$h] = $v;
		        }
		    }
		    $lastHeader = end($headers);

		    $response['code'] = $lastHeader['Status'];
		    preg_match('/HTTP[^\s]* ([0-9]*) (.*)/i',$lastHeader['Status'],$match);
		    $response['code'] = $match[1];
		    $response['message'] = $match[2];
		}else{
			$response['message'] = 'Pas de détails';
		}
	}catch(Exception $e){
		$response['code'] = 500;
		$response['message'] = $e->getMessage();
	}
	return $response;
}

function host_cron($time){

		global $conf,$_;

		if(!in_array(date('H:i', $time), array(5,10,15,20,25,30,35,40,45,50,55,0)) && !isset($_['force-host']) ) return;

		$errors = array();
		$resolved = array();
		require_once(__DIR__.SLASH.'Machine.class.php');
		require_once(__DIR__.SLASH.'MachineApplication.class.php');
		Plugin::need('client/Client');

		foreach (MachineApplication::loadAll(array('monitored'=>1),  null,  null, array('*'),  2) as $key => $application) {

			if(empty($application->url)) continue;

				$machine = $application->join('machine');

				$pendingDown = History::load(array('uid'=>$application->id,'scope'=>'host_application','meta'=>null,'type'=>'down'));

				foreach(explode(',',$application->url) as $url){
					$response = host_ping_url($url);

					echo $response['code'].' : '. $url.PHP_EOL;

					if($response['code']!=200){
						$item = new History();
						$item->uid = $application->id;
						$item->scope = 'host_application';
						$item->type = 'down';
						$item->comment = 'L\'application est en erreur avec le code '. $response['code'].' : '.$response['message'];
						if(!$pendingDown){
							$errors[] = array('machine'=>$machine,'application'=>$application,'ping'=>$response);
							$item->save();
						}
					}else{

						if(!is_object($pendingDown)) continue;

						$pendingDown->meta = json_encode(array('resolved' => time()));
						$pendingDown->save();

						$item = new History();
						$item->uid = $application->id;
						$item->scope = 'host_application';
						$item->type = 'up';
						$item->comment = 'L\'application est de nouveau opérationnelle après '.relative_time($item->created,time()).' d\'inactivité';
						$item->save();

						$resolved[]= array('machine'=>$machine,'application'=>$application,'ping'=>$response,'down'=>$pendingDown);
					}

			}


		}


		if(count($errors) > 0){

			if(count($errors)>1){
				$title = '🔥 '.count($errors).' noms de domaines ne répondent plus';
				$message = '<p>Les noms de domaines suivants sont down :<p><ul> ';
			}else{
				$title = '🔥 '.count($errors).' nom de domaine ne répond plus';
				$message = '<p>Le nom de domaine suivant est down :<p><ul> ';
			}

			foreach($errors as $error){
				$machine = $error['machine'];
				$application = $error['application'];
				$ping = $error['ping'];

				$json = json_encode(array(
					'action' =>'putty_open',
					'ip' => $machine->ip
				));

				$message .= '<li style="padding:15px;border-bottom:1px solid #cecece;">';
				$message .= '<a href="'.$application->url.'">'.$application->url.'</a>';
				$message .= ' Hebergement : <strong><a href="dev://'.base64_encode($json).'">'.$machine->label.'</a></strong>';
				if(!empty($application->id)) $message .= '<br>Application : <strong>'.$application->label.'</strong>';
				if(!empty($machine->ip)) $message .= '<br> IP : <strong>'.$machine->ip.'</strong>';
				$message .= '<br> Erreur : <strong>'.$ping['code'].' : '.$ping['message'].'</strong>';

				$message .= '</li>';

			}
			$message .= '</ul>';


			// GESTION ENVOI NOTIFICATION
			Plugin::callHook('emit_notification',array(
				array(
					'label' => $title,
					'html' => $message,
					'type' => "host_url_error",
					'meta' => array('link' => ROOT_URL.'/index.php?module=host'),
					'recipients' => array_unique(explode(',',$conf->get('host_url_notification'))) // recipients contient login
				)
			));
		}

		if(count($resolved) > 0){

			if(count($resolved)>1){
				$title = '✔️ '.count($resolved).' noms de domaines répondent à nouveau';
				$message = '<p>Les noms de domaines suivants sont de nouveau en ligne :<p><ul> ';
			}else{
				$title = '✔️ '.count($resolved).' nom de domaine répond à nouveau';
				$message = '<p>Le nom de domaine suivant est de nouveau en ligne :<p><ul> ';
			}

			foreach($resolved as $resolvedItem){
				$machine = $resolvedItem['machine'];
				$application = $resolvedItem['application'];
				$ping = $resolvedItem['ping'];
				$down = $resolvedItem['down'];
				$json = json_encode(array(
					'action' =>'putty_open',
					'ip' => $machine->ip
				));

				$message .= '<li style="padding:15px;border-bottom:1px solid #cecece;">';
				$message .= '<a href="'.$application->url.'">'.$application->url.'</a>';
				$message .= ' Machine : <strong><a href="dev://'.base64_encode($json).'">'.$machine->label.'</a></strong>';
				if(!empty($application->id)) $message .= '<br>Application : <strong>'.$application->label.'</strong>';
				if(!empty($machine->ip)) $message .= '<br> IP : <strong>'.$machine->ip.'</strong>';
				$message .= '<br> Erreur initiale: <strong>'.$down->comment.'</strong>';
				if(!is_array($down->meta)) $down->meta = json_decode($down->meta,true);
				$message .= '<br> Résolu depuis : <strong>'.date('d/m/Y H:i',$down->meta['resolved']).' (Temps de down: '.str_replace(array('Dans ','Il y a '),'',relative_time($down->created,$down->meta['resolved'])).')</strong>';

				$message .= '</li>';
			}
			$message .= '</ul>';

			// GESTION ENVOI NOTIFICATION
			Plugin::callHook('emit_notification',array(array(
					'label' => $title,
					'html' => $message,
					'type' => "host_url_error",
					'meta' => array('link' => ROOT_URL.'/index.php?module=host'),
					'recipients' => array_unique(explode(',',$conf->get('host_url_notification'))) // recipients contient login
				)
			));
		}
}

//Déclaration des settings de base
//Types possibles : voir FieldType.class.php. Un simple string définit une catégorie.
Configuration::setting('host',array(
    "Général",
    'host_url_notification' => array("label"=>"Notifier en cas de down","type"=>"user","attributes"=>array('data-types'=>'"user,rank"','data-multiple'=>'"true"'))
));


Right::register('host',array('label'=>"Gestion des droits sur le module hebergement"));

//Droits ciblés sur les fiches client
Right::register('host_sheet',array(
		'label'=>'Gestion des droits sur une fiche hebergement particuliere',
		'global'=> false,
		'check' => function($action,$right){
			global $myUser;
			require_once(__DIR__.SLASH.'Machine.class.php');
			if($right->uid <= 0) throw new Exception('Id non spécifié');
			$machine = Machine::getById($right->uid);
			if(!$machine) throw new Exception('Machine inexistante');
			if(!$myUser->can('host','edit')) throw new Exception('Seul le un editeur d\'hébergement peut définir des droits pour cette fiche');
			if($machine->creator != $myUser->login) throw new Exception('Seul le créateur de la fiche peut ajouter des droits dessus');
		}
));


function host_notification_type(&$types){
	$types['host_url_error'] = array(
		'category' =>'Développement',
		'label' =>'Machine en erreur',
		'color' =>'#82c91e',
		'icon'  =>'fas fa-server',
		'description' => "Lorsqu'un nom de domaine de machine ne répond plus",
		'default_methods' => array(
			'interface' => true,
			'mail' => false
		)
	);
}
function host_history_type(&$types){
	require_once(__DIR__.SLASH.'MachineApplication.class.php');
	$types[MachineApplication::TYPE_DOWN] = array(
		'slug'=>MachineApplication::TYPE_DOWN,
		'label' => 'Application en erreur',
		'icon' => 'fas fa-thumbs-down',
		'color' => '#da6234');

	$types[MachineApplication::TYPE_UP] = array(
		'slug'=>MachineApplication::TYPE_UP,
		'label' => 'Application rétablie',
		'icon' => 'far fa-thumbs-up',
		'color' => '#28a745');
}

//Déclation des assets
Plugin::addCss("/css/main.css");
Plugin::addJs("/js/main.js");

//Mapping hook / fonctions
Plugin::addHook("install", "host_install");
Plugin::addHook("uninstall", "host_uninstall");

Plugin::addHook("menu_main", "host_menu");
Plugin::addHook("page", "host_page");
Plugin::addHook("menu_setting", "host_menu_setting");
Plugin::addHook("content_setting", "host_content_setting");
Plugin::addHook("cron", "host_cron");
Plugin::addHook("notification_type", "host_notification_type");
Plugin::addHook("history_type", "host_history_type");
?>