<?php
require_once 'includes/class-encription.php';
require_once 'app/class-alert-manager.php';
require_once 'app/class-dataset.php';
require_once 'app/class-user.php';

/**
 * EFPcollect Context
 *
 * Context for DataSet Record publication at EFP level
 *
 * @author ba - Advantis
 * @version 1.0.1
 * @package Backend\FilesJobs
 */
class context_efpwsget extends context {
	public $contextname = "efpwsget";
	function context_efpwsget() {
	}
	
	/**
	 * Default action job mainline
	 */
	function index() {
		
		if (Session::get_user ()) {
			
			$processingUser = Session::get_user ()->id;
			$processingUsername = $user->username;
			$processingRole = Session::get_activerole ()->roleid;
			$processingOrg = Session::get_org ()->id;
		} else { // batch
			
			$processingUser = __USER_SYSTEM;
			$user = new User ( $processingUser );
			$processingUsername = $user->username;
			$processingRole = __ROLE_DATA_MANAGER;
			$processingOrg = __DATA_COLLECTOR_ORGANISATION;
		}

		LogManagement::log ( " JOB :  EFP Push Files : start ", "other", "JOB", __LOGTYPE_DATA, __LOGLEVEL_AUDIT, $processingUsername );
		
		$em = new EntityManager ( 'vw_organisationproviders' );
		
		if (isset ( $_GET ['orgid'] )) {
			
			$orgid = filter_input ( INPUT_GET, 'orgid', FILTER_VALIDATE_INT );
			if ($orgid === false) {
				LogManagement::log ( " JOB :  EFP Push Files : orgid not numeric ", "other", "JOB", __LOGTYPE_SECURITY, __LOGLEVEL_ERROR, $processingUsername );
				// TODO : new alert type for security manager AlertManager::new_alert(ALERT::TYPE_JOB_EFP_PUSH_ERROR, $processingRole, $processingOrg, null, null);
				
				return;
			} else {
				$orglist = $em->load ( 'id = :orgid' , array(':orgid' => $orgid) );
			}
		} else {
			
			$orglist = $em->load ();
		}
		
		foreach ( $orglist as $org ) { /* loop orgs */
			
			$orgid = $org->id;
			
			$objLattestSetV = new stdClass ();
			$objLattestSetT = new stdClass ();
			
			$objLattestSetV->xml = null;
			$objLattestSetV->id = null;
			$objLattestSetV->type = null;
			
			$objLattestSetT->xml = null;
			$objLattestSetT->id = null;
			$objLattestSetT->type = null;
			
			$duplicatesFilesT = array ();
			$duplicatesFilesV = array ();
			
			$result = '';
			
			while ( $result != 'nofile' ) { /* repeat until no more files available on organisation */
				
				/**
				 * select last received file based on time for ORG
				 */
				$em = new EntityManager ( 'receivedfiles' );
				
				$files = $em->load ( 'organisationid=:orgid ORDER BY creationdate DESC', array(':orgid' => $orgid) );
				
				$lastfile = $files [0];
				
				if ($lastfile) {
					
					$time = $lastfile->creationdate;
				} else {
					
					$time = 1; /* first time run */
				}
				
				LogManagement::log ( " JOB :  EFP Push Files : NFP " . $org->internationalname . " with last integration = " . $time, "other", "JOB", __LOGTYPE_DATA, __LOGLEVEL_AUDIT, $processingUsername );
				
				$result = $this->getfile ( $time, $org->wsurl );
				
				// TODO : errorcondition = timeout or bad response. Should it be moved to getfile? Before decription?
				/*
				 * AlertManager::new_alert(ALERT::TYPE_JOB_EFP_PUSH_ERROR, $processingRole, $processingOrg, null, $org->internationalname); LogManagement::log ( " JOB : EFP Push Files : NFP ".$org->internationalname." not responding in timely fashion", "other", "JOB", __LOGTYPE_DATA,__LOGLEVEL_ERROR,$processingUsername);
				 */
				
				if ($result) {
					
					if ($result != 'nofile') {
						
						$xmlobj = new SimpleXMLElement ( $result );
						
						$creationdate = ( string ) $xmlobj [0] ['date'];
						
						$fromyear = ( string ) $xmlobj [0] ['fromyear'];
						
						$toyear = ( string ) $xmlobj [0] ['toyear'];
						
						$type = ( string ) $xmlobj [0] ['type'];
						
						$now = time ();
						
						LogManagement::log ( " JOB :  EFP Push Files : file " . $creationdate . "_" . $type, "other", "JOB", __LOGTYPE_DATA, __LOGLEVEL_AUDIT, $processingUsername );
						
						$em = new EntityManager ( 'receivedfiles' );
						
						$obj = new stdClass ();
						$obj->creationdate = $creationdate;
						$obj->organisationid = $orgid;
						$obj->receptiondate = $now;
						$obj->fromyear = $fromyear;
						$obj->toyear = $toyear;
						$obj->statuscodeid = __RECORD_STATUS_UNCOMPLETED;
						$obj->publishcodeid = __PUBLISHED_STATUS_UNPUBLISHED;
						$obj->filetypeid = 1;
						$obj->userid = $processingUser;
						
						$statisticaltypeid = null;
						
						if ($type == 'victims') {
							$statisticaltypeid = __STATISTICAL_TYPE_VICTIMS;
						}
						
						if ($type == 'traffickers') {
							$statisticaltypeid = __STATISTICAL_TYPE_TRAFFICKERS;
						}
						
						$obj->statisticaltypeid = $statisticaltypeid;
						
						$receivedfile = $em->create ( $obj );
						
						if (! isset ( $receivedfile->id )) {
							AlertManager::new_alert ( ALERT::TYPE_JOB_EFP_PUSH_ERROR, $processingRole, $processingOrg, null, $org->internationalname );
							LogManagement::log ( "JOB :  EFP Push Files : error inserting DB file from  org =" . $orgid . " with creationdate and type :  " . $creationdate . "_" . $type, "other", "JOB", __LOGTYPE_DATA, __LOGLEVEL_ERROR, $processingUsername );
							exit ();
						}
						
						$fileok = $this->savefile ( $result, $orgid, $type, $receivedfile->id );
						
						if (! $fileok) {
							
							$dserr = new Dataset ( $receivedfile->id );
							$dserr->statuscodeid = __RECORD_STATUS_WITH_ERRORS;
							$dserr->save ();
							AlertManager::new_alert ( ALERT::TYPE_JOB_EFP_PUSH_ERROR, $processingRole, $processingOrg, $receivedfile->id, $org->internationalname );
							LogManagement::log ( " JOB :  EFP Push Files : error saving to disk - file " . $creationdate . "_" . $type, "other", "JOB", __LOGTYPE_DATA, __LOGLEVEL_ERROR, $processingUsername );
							exit ();
						} else {
							if ($receivedfile->statisticaltypeid == __STATISTICAL_TYPE_VICTIMS) {
								
								if ($objLattestSetV->xml == null) {
									$objLattestSetV->xml = $xmlobj;
									$objLattestSetV->id = $receivedfile->id;
									$objLattestSetV->type = $type;
								} else {
									array_push ( $duplicatesFilesV, $objLattestSetV->id );
									// save lattest
									$objLattestSetV->xml = $xmlobj;
									$objLattestSetV->id = $receivedfile->id;
									$objLattestSetV->type = $type;
								}
							} elseif ($receivedfile->statisticaltypeid == __STATISTICAL_TYPE_TRAFFICKERS) {
								if ($objLattestSetT->xml == null) {
									$objLattestSetT->xml = $xmlobj;
									$objLattestSetT->id = $receivedfile->id;
									$objLattestSetT->type = $type;
								} else {
									array_push ( $duplicatesFilesT, $objLattestSetT->id );
									// save lattest
									$objLattestSetT->xml = $xmlobj;
									$objLattestSetT->id = $receivedfile->id;
									$objLattestSetT->type = $type;
								}
							}
						}
					}
				}
			}
			
			// here process las updates and process if exists
			if ($objLattestSetV->xml != null) {
				LogManagement::log ( " JOB :  EFP Push Files : NFP Process macrodata Victims ", "other", "JOB", __LOGTYPE_DATA, __LOGLEVEL_AUDIT, $processingUsername );
				
				$this->insertfileondb ( $objLattestSetV->xml, $objLattestSetV->type, $objLattestSetV->id );
				
				// TODO : errorcondition = DB error must terminate transaction rollback
				/*
				 * AlertManager::new_alert(ALERT::TYPE_JOB_EFP_PUSH_ERROR, $processingRole, $processingOrg, null, $org->internationalname); LogManagement::log ( " JOB : EFP Push Files : error staging file ".$objLattestSetV->id."_".$objLattestSetV->type, "other", "JOB", __LOGTYPE_DATA,__LOGLEVEL_ERROR,$processingUsername);
				 */
				
				$da = new DataAccess ();
				
				$args = array ();
				
				array_push ( $args, $da->helper_args ( 'recfileid', $objLattestSetV->id, $da::TYPE_INTEGER ) );
				array_push ( $args, $da->helper_args ( 'userid', $processingUser, $da::TYPE_INTEGER ) );
				
				$sql = "select base.processmacrodata(:recfileid,:userid )";
				
				$res = $da->func_get ( $sql, $args );
				
				if ($res == null || $res [0]->processmacrodata != '') {
					AlertManager::new_alert ( ALERT::TYPE_JOB_EFP_PUSH_ERROR, $processingRole, $processingOrg, $objLattestSetV->id, $org->internationalname );
					LogManagement::log ( " JOB :  EFP Push Files : processmacrodata file " . $objLattestSetV->id . "_" . $objLattestSetV->type, "other", "JOB", __LOGTYPE_DATA, __LOGLEVEL_ERROR, $processingUsername );
					// TODO : should stop cycle?
				} else {
					$ds = new Dataset ( $objLattestSetV->id );
					$ds->statuscodeid = __RECORD_STATUS_COMPLETED;
					$ds->save ();
					
					foreach ( $duplicatesFilesV as $dup ) {
						$ds = new Dataset ( $dup );
						$ds->statuscodeid = __RECORD_STATUS_DUPLICATE;
						$ds->save ();
					}
				}
			}
			
			if ($objLattestSetT->xml != null) {
				LogManagement::log ( " JOB :  EFP Push Files : NFP Process macrodata traffickers ", "other", "JOB", __LOGTYPE_DATA, __LOGLEVEL_AUDIT, $processingUsername );
				
				$this->insertfileondb ( $objLattestSetT->xml, $objLattestSetT->type, $objLattestSetT->id );
				
				// TODO : errorcondition = DB error must terminate transaction rollback
				/*
				 * AlertManager::new_alert(ALERT::TYPE_JOB_EFP_PUSH_ERROR, $processingRole, $processingOrg, null, $org->internationalname); LogManagement::log ( " JOB : EFP Push Files : error staging file ".$objLattestSetV->id."_".$objLattestSetV->type, "other", "JOB", __LOGTYPE_DATA,__LOGLEVEL_ERROR,$processingUsername);
				 */
				
				$da = new DataAccess ();
				
				$args = array ();
				
				array_push ( $args, $da->helper_args ( 'recfileid', $objLattestSetT->id, $da::TYPE_INTEGER ) );
				array_push ( $args, $da->helper_args ( 'userid', $processingUser, $da::TYPE_INTEGER ) );
				
				$sql = "select base.processmacrodata(:recfileid,:userid )";
				
				$res = $da->func_get ( $sql, $args );
				
				if ($res == null || $res->processmacrodata != '') {
					AlertManager::new_alert ( ALERT::TYPE_JOB_EFP_PUSH_ERROR, $processingRole, $processingOrg, $objLattestSetT->id, $org->internationalname );
					LogManagement::log ( " JOB :  EFP Push Files : processmacrodata file " . $objLattestSetT->id . "_" . $objLattestSetT->type, "other", "JOB", __LOGTYPE_DATA, __LOGLEVEL_ERROR, $processingUsername );
					// TODO : should stop cycle?
				} else {
					$ds = new Dataset ( $objLattestSetT->id );
					$ds->statuscodeid = __RECORD_STATUS_COMPLETED;
					$ds->save ();
					
					foreach ( $duplicatesFilesT as $dup ) {
						$ds = new Dataset ( $dup );
						$ds->statuscodeid = __RECORD_STATUS_DUPLICATE;
						$ds->save ();
					}
				}
			}
		}
		
		LogManagement::log ( " JOB :  EFP Push Files : end ", "other", "JOB", __LOGTYPE_DATA, __LOGLEVEL_AUDIT, $processingUsername );
	}
	
	/**
	 * Uses web service url to get next update file from timestamp
	 *
	 * @param string $time        	
	 * @param string $wsurl        	
	 * @return string|number
	 */
	function getfile($time, $wsurl) {
		$baseurl = $wsurl;
		
		$url = $baseurl . '?t=' . $time;
		
		echo $url . '<br>';
		
		$file = fopen ( $url, "r" );
		
		if ($file) {
			$result = '';
			
			while ( ! feof ( $file ) ) {
				$result .= fgets ( $file );
			}
			
			if ($result != 'nofile' && $result != '') {
				
				$encription = new Encryption ( '87!#$%/&&)=/lkhnLKH' );
				
				$result = $encription->decrypt ( $result );
			}
			
			return $result;
		}
		
		return 0;
	}
	
	/**
	 * Saves stream receceived to correct NFP id folder and statistical type
	 *
	 * @param string $contents        	
	 * @param int $nfpid        	
	 * @param string $type        	
	 * @param int $id        	
	 * @return number
	 */
	function savefile($contents, $nfpid, $type, $id) {
		$basepath = __EFP_IMPORT_FILE_PATH;
		
		$filename = $id;
		
		$path = $basepath . '/' . $nfpid . '/' . $type;
		
		if (! file_exists ( $basepath . '/' . $nfpid )) {
			mkdir ( $basepath . '/' . $nfpid, true );
		}
		
		if (! file_exists ( $path )) {
			mkdir ( $path, true );
		}
		
		$file = fopen ( $path . '/' . $filename, "w" );
		
		if (! $file)
			return 0; // fail writing file
		
		fwrite ( $file, $contents );
		
		fclose ( $file );
		
		return 1;
	}
	
	/**
	 * Load XML object to DB table for staging purposes
	 *
	 * @param object $xmlobj        	
	 * @param string $type        	
	 * @param int $receivedfileid        	
	 */
	function insertfileondb($xmlobj, $type, $receivedfileid) {
		$em = new EntityManager ( 'imp' . $type, 'STAGING' );
		
		foreach ( $xmlobj->record as $record ) {
			
			$obj = new stdClass ();
			
			foreach ( $record as $key => $value ) {
				
				$obj->$key = $value; // convert xmlobj to stclass
			}
			
			$obj->receivedfileid = $receivedfileid;
			
			$em->create ( $obj );
		}
	}
}	