<?php
require_once "class-version-manager.php";
require_once "class-version.php";
require_once "class-data-structures.php";
require_once "class-data-provisions.php";
require_once 'includes/data-access/class-transaction.php';

/**
 * Data Structures managers
 * 
 */

/**
 * Manager class for datastructures NDP level (1)
 * 
 * @author tm - Advantis Solutions
 * @version 1.0.1
 * @package Backend\DataStructures
 */
class DataStructuresNDPManager {
	
	/**
	 * Validates if NDP is active
	 *
	 * @param integer $id        	
	 * @return boolean
	 */
	function is_live($id) {
		$dsd = new DataStructures ( $id );
		if ($dsd->active == 1) {
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * Validates if NDP is Draft
	 *
	 * @param DataStructures $dsd        	
	 * @return boolean
	 */
	function is_draft(DataStructures $dsd) {
		$ver = new Version ( $dsd->versionregistryid );
		if ($dsd->active == 1) {
			return false;
		} elseif ($ver->validto) {
			return false;
		} else {
			return true;
		}
	}
	
	/**
	 * Gets questions of a NDP
	 *
	 * @param DataStructures $dsd        	
	 * @return array[EntityManager("dsdquestions")]
	 */
	function get_questions(DataStructures $dsd) {
		$result = array ();
		
		if ($dsd && $dsd->levelcodeid == DataStructures::LEVEL_NDP) {
			
			$eql = new EntityManager ( "dsdquestions" );
			$result = $eql->load ( 'datastructuredefinitionid=?', array (
					$dsd->id 
			) );
		}
		
		return $result;
	}
	
	/**
	 * Validates if NDP can go live
	 *
	 * @param DataStructures $dsd        	
	 * @return boolean
	 */
	function can_go_live(DataStructures $dsd) {
		if ($dsd && $dsd->levelcodeid == DataStructures::LEVEL_NDP) {
			
			$vm = new VersionManager ();
			
			$em = new EntityManager ( DataStructures::BASEENTITY );
			
			// Only one active NDP for each statisticaltypeid
			
			$results = $em->load ( "levelcodeid=:levelcodeid and statisticaltypeid=:statisticaltypeid and active=true", array(':levelcodeid' => DataStructures::LEVEL_NDP, ':statisticaltypeid' => $dsd->statisticaltypeid) );
			
			if (count ( $results ) == 0 && ! $vm->is_closed_version ( $dsd->versionregistryid )) {
				return true;
			} else {
				return false;
			}
		}
		
		return false;
	}
	
	/**
	 * Validates if NDP can be disabled
	 *
	 * @param DataStructures $dsd        	
	 * @return boolean
	 */
	function can_be_disabled(DataStructures $dsd) {
		if ($dsd && $dsd->levelcodeid == DataStructures::LEVEL_NDP) {
			
			$em = new EntityManager ( DataStructures::BASEENTITY );
			
			// every child element must not be active
			$results = $em->load ( "levelcodeid=:levelcodeid and statisticaltypeid=:statisticaltypeid and active=true and parentid = :parentid" , array(':levelcodeid' => DataStructures::LEVEL_LDP, 'statisticaltypeid' => $dsd->statisticaltypeid, ':parentid' => $dsd->id) );
			
			if (count ( $results ) == 0 && $dsd->active == 1) {
				return true;
			} else {
				return false;
			}
		}
		
		return false;
	}
	
	/**
	 * Enables NDP
	 *
	 * @param DataStructures $dsd        	
	 * @return boolean
	 */
	function go_live(DataStructures $dsd) {
		$result = true;
		try {
			
			Transaction::beginTransaction ();
			
			if ($dsd && $dsd->levelcodeid == DataStructures::LEVEL_NDP && $this->can_go_live ( $dsd )) {
				
				$vm = new VersionManager ();
				
				if ($vm->start_version ( $dsd->versionregistryid )) {
					$dsd->active = 1;
					$dsd->save ();
					
					Transaction::commit ();
				}
			}
		} catch ( Exception $exp ) {
			Transaction::rollback ();
			dump_errorlog ( 'DataStructuresNDPManager', 'go_live', $exp->getMessage () );
			$result = false;
		}
		
		return $result;
	}
	
	/**
	 * Disables NDP must validate tha all LDP child are not active
	 *
	 * @param DataStructures $dsd        	
	 * @return boolean
	 */
	function disable(DataStructures $dsd) {
		$result = true;
		try {
			
			Transaction::beginTransaction ();
			
			if ($dsd && $dsd->levelcodeid == DataStructures::LEVEL_NDP && $this->can_be_disabled ( $dsd )) {
				
				$vm = new VersionManager ();
				if ($vm->close_version ( $dsd->versionregistryid )) {
					$dsd->active = 0;
					$dsd->save ();
					
					Transaction::commit ();
				}
			}
		} catch ( Exception $exp ) {
			Transaction::rollback ();
			dump_errorlog ( 'DataStructuresNDPManager', 'disable', $exp->getMessage () );
			$result = false;
		}
		
		return $result;
	}
	
	/**
	 * Save new NDP from another in new version
	 *
	 * @param DataStructures $dsd        	
	 * @return integer
	 */
	function save_new_from(DataStructures $dsd) {
		$newid;
		$needrollback = false;
		
		try {
			
			Transaction::beginTransaction ();
			
			$em = new EntityManager ( DataStructures::BASEENTITY );
			
			// New version from version id
			$version = new Version ( $dsd->versionregistryid );
			$newversion = new Version ();
			$description = $dsd->description;
			$newversion->setNew ( $version->code, $version->annotation, $description );
			
			$em = new EntityManager ( $newversion::BASEENTITY );
			$newversion = $em->create ( $newversion );
			
			if ($newversion->id) {
				$newdsd = new DataStructures ();
				
				$newdsd->setNew ( $dsd->statisticaltypeid, $dsd::LEVEL_NDP, $newversion->id, $dsd->description );
				$em = new EntityManager ( $newdsd::BASEENTITY );
				
				$newdsd = $em->create ( $newdsd );
				
				if ($newdsd->id) {
					
					$da = new DataAccess ();
					$cfgdb = new ConfigDB ();
					$schema = $cfgdb->connections ["DEFAULT"] ["DBSCHEMA"];
					$da->func_get ("INSERT INTO " . $schema . ".dsdquestions (datastructuredefinitionid, questionid, void, voidreasoncodeid) select " . $newdsd->id . ", questionid, void, voidreasoncodeid from base.dsdquestions where datastructuredefinitionid = :datastructureid", array(':datastructureid' => $dsd->id) );			
					
					$newid = $newdsd->id;
				} else { // error on getting DSD
					$needrollback = true;
				}
			} else { // error on getting version
				$needrollback = true;
			}
			
			if ($needrollback) {
				Transaction::rollback ();
			} else {
				Transaction::commit ();
			}
		} catch ( Exception $exp ) {
			Transaction::rollback ();
			dump_errorlog ( 'DataStructuresNDPManager', 'save_new_From', $exp->getMessage () );
		}
		
		return $newid;
	}
}

/**
 * Manager class for datastructures LDP level (2)
 * 
 * @author tm - Advantis Solutions
 * @version 1.0.1
 * @package Backend\DataStructures
 */
class DataStructuresLDPManager {
	
	/**
	 * Validates if LDP is active
	 *
	 * @param integer $id        	
	 * @return boolean
	 */
	function is_live($id) {
		$dsd = new DataStructures ( $id );
		if ($dsd->active == 1) {
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * Validates if LDP is draft
	 *
	 * @param DataStructures $dsd        	
	 * @return boolean
	 */
	function is_draft(DataStructures $dsd) {
		$ver = new Version ( $dsd->versionregistryid );
		if ($dsd->active == 1) {
			return false;
		} elseif ($ver->validto) {
			return false;
		} else {
			return true;
		}
	}
	
	/**
	 * checks if exists parent structure to allow new LDP
	 *
	 * @param integer $statistical_type
	 *        	(__STATISTICAL_TYPE_TRAFFICKERS:__STATISTICAL_TYPE_VICTIMS)
	 * @return boolean
	 */
	function can_add_new($statistical_type) {
		$em = new EntityManager ( DataStructures::LISTVIEW );
		
		// checks for NDP of statisticaltypeid
		
		$results = $em->load ( "datastructuredefinitions_levelcodeid=:levelcodeid and datastructuredefinitions_statisticaltypeid=:statisticaltypeid and versionregistry_validto is null", array(':levelcodeid' => DataStructures::LEVEL_NDP, ':statisticaltypeid' => $statistical_type) );
		
		if (count ( $results ) == 0) {
			return false;
		} else {
			return true;
		}
	}
	
	/**
	 * Validates if LDP can go live
	 *
	 * @param DataStructures $dsd        	
	 * @return boolean
	 */
	function can_go_live(DataStructures $dsd) {
		if ($dsd && $dsd->levelcodeid == DataStructures::LEVEL_LDP) {
			
			$dsdm = new DataStructuresNDPManager ();
			// The parent datastructuredefinitionid must be active
			if ($dsdm->is_live ( $dsd->parentid ) && $this->is_draft ( $dsd )) {
				return true;
			}
		}
		
		return false;
	}
	
	/**
	 * Validates if LDP can be disabled
	 *
	 * @param DataStructures $dsd        	
	 * @return boolean
	 */
	function can_be_disabled(DataStructures $dsd) {
		if ($dsd && $dsd->levelcodeid == DataStructures::LEVEL_LDP) {
			
			$em = new EntityManager ( DataProvisions::BASEENTITY );
			
			// every child element must not be active
			$results = $em->load ( " datastructuredefinitionid=:dsdid and active= true ", array(':dsdid' => $dsd->id ) );
			
			if (count ( $results ) == 0 && $dsd->active == 1) {
				return true;
			} else {
				return false;
			}
		}
		
		return false;
	}
	
	/**
	 * Enables LDP
	 *
	 * @param DataStructures $dsd        	
	 * @return boolean
	 */
	function go_live(DataStructures $dsd) {
		$result = true;
		try {
			
			Transaction::beginTransaction ();
			
			if ($dsd && $dsd->levelcodeid == DataStructures::LEVEL_LDP && $this->can_go_live ( $dsd )) {
				
				$vm = new VersionManager ();
				if ($vm->start_version ( $dsd->versionregistryid )) {
					$dsd->active = 1;
					$dsd->save ();
					
					Transaction::commit ();
				}
			}
		} catch ( Exception $exp ) {
			Transaction::rollback ();
			dump_errorlog ( 'DataStructuresLDPManager', 'go_live', $exp->getMessage () );
			$result = false;
		}
		
		return $result;
	}
	
	/**
	 * Disables LDP
	 *
	 * @param DataStructures $dsd        	
	 * @return boolean
	 */
	function disable(DataStructures $dsd) {
		$result = true;
		try {
			
			Transaction::beginTransaction ();
			
			if ($dsd && $dsd->levelcodeid == DataStructures::LEVEL_LDP && $this->can_be_disabled ( $dsd )) {
				
				$vm = new VersionManager ();
				if ($vm->close_version ( $dsd->versionregistryid )) {
					$dsd->active = 0;
					$dsd->save ();
					
					Transaction::commit ();
				}
			}
		} catch ( Exception $exp ) {
			Transaction::rollback ();
			dump_errorlog ( 'DataStructuresLDPManager', 'disable', $exp->getMessage () );
			$result = false;
		}
		
		return $result;
	}
	
	/**
	 * Save new LDP from another in new version
	 *
	 * @param DataStructures $dsd        	
	 * @return integer
	 */
	function save_new_from(DataStructures $dsd) {
		$newid;
		$needrollback = false;
		
		try {
			
			Transaction::beginTransaction ();
			$em = new EntityManager ( DataStructures::BASEENTITY );
			
			// New version from version id
			$version = new Version ( $dsd->versionregistryid );
			$newversion = new Version ();
			$description = $dsd->description;
			$newversion->setNew ( $version->code, $version->annotation, $description );
			
			$em = new EntityManager ( $newversion::BASEENTITY );
			$newversion = $em->create ( $newversion );
			
			if ($newversion->id) {
				$newdsd = new DataStructures ();
				
				$newdsd->setNew ( $dsd->statisticaltypeid, $dsd::LEVEL_LDP, $newversion->id, $dsd->description );
				
				$newdsd->parentid = $dsd->parentid;
				$em = new EntityManager ( $newdsd::BASEENTITY );
				
				$newdsd = $em->create ( $newdsd );
				
				if ($newdsd->id) {
					
					$da = new DataAccess ();
					$cfgdb = new ConfigDB ();
					$schema = $cfgdb->connections ["DEFAULT"] ["DBSCHEMA"];
					
					$da->func_get ("INSERT INTO " . $schema . ".dsdquestions (datastructuredefinitionid, questionid, void, voidreasoncodeid) select " . $newdsd->id . ", questionid, void, voidreasoncodeid from base.dsdquestions where datastructuredefinitionid = :datastructureid", array(':datastructureid' => $dsd->id)  );
					
					$newid = $newdsd->id;
				} else { // error on getting DSD
					$needrollback = true;
				}
			} else { // error on getting version
				$needrollback = true;
			}
			
			if ($needrollback) {
				Transaction::rollback ();
			} else {
				Transaction::commit ();
			}
		} catch ( Exception $exp ) {
			Transaction::rollback ();
			dump_errorlog ( 'DataStructuresLDPManager', 'save_new_From', $exp->getMessage () );
		}
		
		return $newid;
	}
	
	/**
	 * Gets questions of a LDP
	 *
	 * @param DataStructures $dsd        	
	 * @return array[EntityManager("dsdquestions")]
	 */
	function get_questions(DataStructures $dsd) {
		$result = array ();
		
		if ($dsd && $dsd->levelcodeid == DataStructures::LEVEL_LDP) {
			
			$eql = new EntityManager ( "dsdquestions" );
			$result = $eql->load ( 'datastructuredefinitionid=?', array (
					$dsd->id 
			) );
		}
		
		return $result;
	}
}

/**
 * Manager class for datastructures DPA level (3)
 * 
 * @author tm - Advantis Solutions
 * @version 1.0.1
 * @package Backend\DataStructures
 */
class DataStructuresDPAManager {
	
	/**
	 * Validates if DPA is draft
	 *
	 * @param DataProvisions $dpa        	
	 * @return boolean
	 */
	function is_draft(DataProvisions $dpa) {
		$ver = new Version ( $dpa->versionregistryid );
		if ($dpa->active == 1) {
			return false;
		} elseif ($ver->validto) {
			return false;
		} else {
			return true;
		}
	}
	
	/**
	 * Validates if DPA can go live
	 *
	 * @param DataProvisions $dpa        	
	 * @return boolean
	 */
	function can_go_live(DataProvisions $dpa) {
		if ($dpa && $this->is_draft ( $dpa )) {
			
			$dsdm = new DataStructuresLDPManager ();
			// The parent datastructuredefinitionid must be active
			if ($dsdm->is_live ( $dpa->datastructuredefinitionid )) {
				$em = new EntityManager ( DataProvisions::LISTVIEW );
				
				// From this organisation there should be only one active DPA for each statisticaltypeid
				$results = $em->load ( "provisionagreements_id=:dpaid", array(':dpaid' => $dpa->id)  );
				
				if (count ( $results ) == 1) {
					$listOrg = $em->load ( "provisionagreements_fromorganisationid=:fromorganisationid and datastructuredefinitions_statisticaltypeid = :statisticaltypeid and provisionagreements_active = true ", array(':fromorganisationid' => $dpa->fromorganisationid, ':statisticaltypeid' => $results [0]->datastructuredefinitions_statisticaltypeid) );
					
					if (count ( $listOrg ) == 0) {
						return true;
					}
				}
			}
		}
		
		return false;
	}
	
	/**
	 * Validates if DPA can be disabled
	 *
	 * @param DataProvisions $dpa        	
	 * @return boolean
	 */
	function can_be_disabled(DataProvisions $dpa) {
		if ($dpa && $dpa->active == 1) {
			return true;
		}
		
		return false;
	}
	
	/**
	 * Enables DPA
	 *
	 * @param DataProvisions $dpa        	
	 * @return boolean
	 */
	function go_live(DataProvisions $dpa) {
		$result = true;
		try {
			
			Transaction::beginTransaction ();
			
			if ($dpa && $this->can_go_live ( $dpa )) {
				
				$vm = new VersionManager ();
				if ($vm->start_version ( $dpa->versionregistryid )) {
					$dpa->active = 1;
					$dpa->save ();
					
					Transaction::commit ();
				}
			}
		} catch ( Exception $exp ) {
			Transaction::rollback ();
			dump_errorlog ( 'DataStructuresDPAManager', 'go_live', $exp->getMessage () );
			$result = false;
		}
		
		return $result;
	}
	
	/**
	 * Disables DPA
	 *
	 * @param DataProvisions $dpa        	
	 * @return boolean
	 */
	function disable(DataProvisions $dpa) {
		$result = true;
		try {
			
			Transaction::beginTransaction ();
			
			if ($dpa && $this->can_be_disabled ( $dpa )) {
				
				$vm = new VersionManager ();
				if ($vm->close_version ( $dpa->versionregistryid )) {
					$dpa->active = 0;
					$dpa->save ();
					
					Transaction::commit ();
				}
			}
		} catch ( Exception $exp ) {
			Transaction::rollback ();
			dump_errorlog ( 'DataStructuresDPAManager', 'disable', $exp->getMessage () );
			$result = false;
		}
		
		return $result;
	}
	
	/**
	 * checks if exists parent structure to allow new DPA
	 *
	 * @param integer $statistical_type
	 *        	(__STATISTICAL_TYPE_TRAFFICKERS:__STATISTICAL_TYPE_VICTIMS)
	 * @return boolean
	 */
	function can_add_new($statistical_type) {
		$em = new EntityManager ( DataStructures::LISTVIEW );
		
		// checks for NDP of statisticaltypeid
		
		$results = $em->load ( "datastructuredefinitions_levelcodeid=:levelcodeid and datastructuredefinitions_statisticaltypeid=:statisticaltypeid and versionregistry_validto is null", array(':levelcodeid' => DataStructures::LEVEL_LDP, ':statisticaltypeid' => $statistical_type) );
		
		if (count ( $results ) == 0) {
			return false;
		} else {
			return true;
		}
	}
	
	/**
	 * Save new DPA from another in new version
	 *
	 * @param DataProvisions $dpa        	
	 * @return integer
	 */
	function save_new_from(DataProvisions $dpa) {
		$newid;
		$needrollback = false;
		
		try {
			
			Transaction::beginTransaction ();
			
			$status = $dpa->active;
			
			$em = new EntityManager ( DataProvisions::BASEENTITY );
			
			// New version from version id
			$version = new Version ( $dpa->versionregistryid );
			$newversion = new Version ();
			$description = $dpa->description;
			$newversion->setNew ( $version->code, $version->annotation, $description );
			
			$em = new EntityManager ( $newversion::BASEENTITY );
			$newversion = $em->create ( $newversion );
			
			if ($newversion->id) {
				$em = new EntityManager ( $dpa::BASEENTITY );
				$dpa->active = 0;
				$newdpa = $em->create ( $dpa );
				
				$dpa->active = $status;
				
				if ($newdsd->id) {
					
					$newid = $newdsd->id;
				} else { // error on getting DSD
					$needrollback = true;
				}
			} else { // error on getting version
				$needrollback = true;
			}
			
			if ($needrollback) {
				Transaction::rollback ();
			} else {
				Transaction::commit ();
			}
		} catch ( Exception $exp ) {
			Transaction::rollback ();
			dump_errorlog ( 'DataStructuresDPAManager', 'save_new_From', $exp->getMessage () );
		}
		
		return $newid;
	}
	/**
	 * Query if the current session user rganisation can collect data for a specific statisticaltype
	 *
	 * @param int $statisticaltypeid        	
	 * @return number value of the active dpa id associated with the session organisation
	 *         0 if session organisation doesn't have an active DPA for statisticaltype
	 */
	function can_collect_data($statisticaltypeid) {
		
		// gets organistation from session
		$org = Session::get_org ();
		
		$today = date ( "Y-m-d" );
		
		if ($org->id) {
			$em = new EntityManager ( DataProvisions::BASEENTITY );
			$list = $em->load ( 'fromorganisationid=? and active = true and validfrom <= ? and validto >=?', array (
					$org->id,
					$today,
					$today 
			) );
			
			foreach ( $list as $dpa ) {
				$ldp = new DataStructures ( $dpa->datastructuredefinitionid );
				
				if ($ldp && $ldp->statisticaltypeid == $statisticaltypeid) {
					return $dpa->id;
				}
			}
		}
		
		return 0;
	}
	
	/**
	 * Gets the bit string representation of the LDP associated with the session user organisation
	 * This string is the string configuration attribute for the lime token
	 * This will allow the survey configuration to show only the configured questions
	 *
	 * @param int $statisticaltypeid        	
	 * @return string
	 */
	function get_token($statisticaltypeid) {
		
		// Get max number questions for $statisticaltypeid (questionslist)
		// start string with max size filled with zeros
		$str = str_pad ( "0", ($statisticaltypeid == __STATISTICAL_TYPE_VICTIMS) ? __STATISTICAL_TYPE_VICTIMS_MAXQUESTIONS : __STATISTICAL_TYPE_TRAFFICKERS_MAXQUESTIONS, "0", STR_PAD_RIGHT );
		
		// from the parent LDP datastructuredefinitionid with the same $statisticaltypeid gets dsdquestions and indexs (questionslist)
		$org = Session::get_org ();
		
		$today = date ( "Y-m-d" );
		
		if ($org->id) {
			$em = new EntityManager ( DataProvisions::BASEENTITY );
			$list = $em->load ( 'fromorganisationid=? and active = true and validfrom <= ? and validto >=?', array (
					$org->id,
					$today,
					$today 
			) );
			
			foreach ( $list as $dpa ) {
				$ldp = new DataStructures ( $dpa->datastructuredefinitionid );
				
				if ($ldp && $ldp->statisticaltypeid == $statisticaltypeid) {
					$em = new EntityManager ( "dsdquestionlist" );
					$ql = $em->load ( 'dsd_id = ?', array (
							$ldp->id 
					) );
					
					// foreach questions sets 1 on the string index
					foreach ( $ql as $question ) {
						if (isset ( $question->questions_index )) {
							$str [$question->questions_index] = '1';
						}
					}
				}
			}
		}
		// returns string
		return $str;
	}
}

?>