<?php

/**
 * Visit class.
 * 
 * @author  Maggie Magpie <oldauntie@oldauntie.org>
 *
 */
class Visit {

	public $vid;
	public $pid;
	public $oid;
	public $uid;
	public $reason_id;
	public $reason;
	public $diagnosis_id;
	public $diagnosis;
	public $teaser;
	public $status_id = 1;
	public $status;
	public $type_id;
	public $type;
	public $created;
	public $created_date;
	public $modified;
	public $modified_date;

	public $notes = array();
	public $drugs = array();
	public $diagnostic_tests = array();
	public $procedures = array();

	
	const STATUS_CANCELLED 	= 0;
	const STATUS_OPENED 	= 1;
	const STATUS_CLOSED		= 2;
        
	
	
	function __construct( $vid = null ) {
		if ( is_null( $vid ) == false ) {
			try {
				$this->load( $vid );
			} catch ( Exception $ex ) {
				// log exception
				Watchdog::write( Watchdog::TYPE_PHP, $ex->getMessage(), $_SESSION ['uid'], Watchdog::WATCHDOG_ERROR );
			}
		}
	}
	
	
	public function isCancelled() {
		return self::isStatus( Visit::STATUS_CANCELLED );
	}
	
	public function isClosed() {
		return self::isStatus( Visit::STATUS_CLOSED );
	}
	
	public function isOpened() {
		return self::isStatus( Visit::STATUS_OPENED );
	}
	
	/**
	 * check object status against a given status_id
	 * @param int $status_id
	 * @return boolean
	 */
	public function isStatus( $status_id ) {
		if( $this->status_id == $status_id ){
			return true;
		}else{
			return false;
		}
	}
	

	/**
	 * general visit load wrapper. Get data from database and load a visit object.
	 * 
	 * @param int	$vid	Visit ID.
	 * 
	 * @return object 
	 */
	public function load( $vid ) {
		$this->loadVisitHead( $vid );
		$this->loadNotes( $vid );
		$this->loadDrugs( $vid );
		$this->loadDiagnosticTests( $vid );
		$this->loadProcedures( $vid );

		return $this;
	}

	/**
	 * Load visit head.
	 * 
	 * @param int	$vid	Visit ID.
	 * 
	 * @return array	data taken from database
	 */
	private function loadVisitHead( $vid ) {
		$con = new Connection();

		$sql = "SELECT * FROM visit WHERE vid = " . $vid;
		
		// execute query...
		$rs = $con->selectOneRow( $sql );

		// if a visit exists, fills visit head
		if ( is_array( $rs ) && !empty( $rs ) ) {
			$this->vid = $rs ['vid'];
			$this->pid = $rs ['pid'];
			$this->oid = $rs ['oid'];
			$this->reason_id = $rs ['reason_id'];
			$this->diagnosis_id = $rs ['diagnosis_id'];
			$this->teaser = $rs ['teaser'];
			$this->status_id = $rs ['status_id'];
			$this->type_id = $rs ['type_id'];
			$this->created = $rs ['created'];
			$this->modified = $rs ['modified'];


			// transform unix timestamp into an human readable of visit 
			$this->created_date = Data::UnixTimestampToDate( $rs['created'] );
			$this->modified_date = Data::UnixTimestampToDate( $rs['modified'] );
			
			
			$this->reason		= Connection::entity_value_load('venom_codes', 'term_name', array( 'country_id' => _DEFAULT_COUNTRY_ID, 'id' => $rs['reason_id'] ) );
			$this->diagnosis	= Connection::entity_value_load('venom_codes', 'term_name', array( 'country_id' => _DEFAULT_COUNTRY_ID, 'id' => $rs['diagnosis_id'] ) );
			$this->status		= Connection::entity_value_load('visit_status', 'status', array( 'status_id' => $rs['status_id'] ) );
			$this->type			= Connection::entity_value_load('visit_type', 'status', array( 'type_id' => $rs['type_id'] ) );
		}

		$con->close();
		return $rs;
	}

	/**
	 * Load visit 's notes from database table "notes".
	 * 
	 * @param int	$vid	Visit ID.
	 * 
	 * @return array
	 */
	private function loadNotes( $vid ) {
		$con = new Connection();
		$sql = "SELECT vn.*, u.firstname, u.lastname 
					FROM visit_notes vn, users u 
					WHERE vn.uid = u.uid
					AND vn.vid = " . $vid;
		
		// execute the query...
		$rs = $con->execute( $sql );
		
		if ( is_array( $rs ) && !empty( $rs ) ) {
			$this->notes = $rs;
		}

		$con->close();
		return $rs;
	}

	private function loadDrugs( $vid ) {
		$con = new Connection();
		$sql = "SELECT * 
					FROM visit_drugs a, drugs b 
						WHERE a.country_id = b.country_id 
						AND a.did = b.did 
						AND a.country_id = '" . _DEFAULT_COUNTRY_ID . "' 
						AND a.vid = $vid";

		// execute query...
		$rs = $con->execute( $sql );

		// if drug exists
		if ( is_array( $rs ) && !empty( $rs ) ) {
			$this->drugs = $rs;
		}

		$con->close();
		return $rs;
	}

	private function loadDiagnosticTests( $vid ) {
		$con = new Connection();
		$sql = "SELECT * 
					FROM visit_diagnostic_tests a, venom_codes b 
						WHERE a.country_id = b.country_id 
							AND a.id = b.id 
							AND a.country_id = '" . _DEFAULT_COUNTRY_ID . "' 
							AND a.vid = $vid";

		// execute query...
		$rs = $con->execute( $sql );

		// if diagnostic test exists
		if ( is_array( $rs ) && !empty( $rs ) ) {
			$this->diagnostic_tests = $rs;
		}

		$con->close();
		return $rs;
	}

	private function loadProcedures( $vid ) {
		$con = new Connection();
		$sql = "SELECT * 
					FROM visit_procedures a, venom_codes b 
						WHERE a.country_id = b.country_id 
							AND a.id = b.id 
							AND a.country_id = '" . _DEFAULT_COUNTRY_ID . "' 
							AND a.vid = $vid";

		// esecute query...
		$rs = $con->execute( $sql );

		// if procedure exists
		if ( is_array( $rs ) && !empty( $rs ) ) {
			$this->procedures = $rs;
		}

		$con->close();
		return $rs;
	}

	/**
	 * Save a visit object into database tables.
	 * 
	 * @return boolean
	 */
	public function save() {
		if ( empty( $this->vid ) == true ) {
			return $this->insert();
		} else {
			return $this->update();
		}
	}

	/**
	 * Insert a new note into database
	 * 
	 * @param array $notes
	 * @return boolean if successful
	 */
	function addNotes( $notes = array() ) {
		$con = new Connection();

		// inserting new notes into database
		if ( is_array( $notes ) && empty( $notes ) == false ) {
			foreach ( $notes as $note ) {
				$sql = "INSERT INTO visit_notes
							(
							vid,
							title,
							text,
							created
							)values("
						. $this->vid . ", "
						. "'" . $con->escape( $note['title'] ) . "', "
						. "'" . $con->escape( $note['text'] ) . "', "
						. "UNIX_TIMESTAMP() )";

				$bRV = $bRV && $con->execute( $sql );
			}
		}

		if ( $bRV == true ) {
			$con->commit();
		} else {
			$con->rollback();
		}

		$con->close();
		return $bRV;
	}

	/**
	 * insert a new visit object into database.
	 * 
	 * @return true if successful
	 */
	public function insert() {
		$con = Connection::getInstance();

		$sql = "INSERT into visit 
					(
	    			vid,
	    			pid,
	    			oid,
	    			reason_id,
	    			diagnosis_id,
	    			teaser,
	    			status_id,
	    			type_id,
	    			created,
	    			modified
						)values("
				. "null,"
				. "'" . $this->pid . "', "
				. "'" . $this->oid . "', "
				. "'" . $this->reason_id . "', "
				. "'" . $this->diagnosis_id . "', "
				. "'" . $this->teaser . "', "
				. "'" . $this->status_id . "', "
				. "'" . $this->type_id . "', "
				. "UNIX_TIMESTAMP(), "
				. "UNIX_TIMESTAMP() 
						)";

		$bRV = $con->execute( $sql );

		// adding insertID to vid
		if ( $bRV == true ) {
			$this->vid = $con->insertID();
		}

		// adding notes to database
		if ( is_array( $this->notes ) && empty( $this->notes ) == false ) {
			foreach ( $this->notes as $note ) {
				$sql = "INSERT INTO visit_notes
							(
							vid,
							uid,
							title,
							text,
							created
							)values("
						. $this->vid . ", "
						. $this->uid . ", "
						. "'" . $con->escape( $note['title'] ) . "', "
						. "'" . $con->escape( $note['text'] ) . "', "
						. "UNIX_TIMESTAMP() )";
							
				$bRV = $bRV && $con->execute( $sql );
			}
		}





		// inserting drugs into database
		if ( is_array( $this->drugs ) && empty( $this->drugs ) == false ) {
			foreach ( $this->drugs as $drug ) {
				$sql = "INSERT INTO visit_drugs
							(
							vid,
							country_id,
							did,
							qty,
							created
							)values("
						. $this->vid . ", "
						. "'" . _DEFAULT_COUNTRY_ID . "', "
						. "'" . $con->escape( $drug['did'] ) . "', "
						. $drug['qty'] . ", "
						. "UNIX_TIMESTAMP() )";
				
				$bRV = $bRV && $con->execute( $sql );
			}
		}



		// inserting diagnostic tests into database
		if ( is_array( $this->diagnostic_tests ) && empty( $this->diagnostic_tests ) == false ) {
			foreach ( $this->diagnostic_tests as $diagnostic_test ) {
				$sql = "INSERT INTO visit_diagnostic_tests
							(
							vid,
							country_id,
							id,
							created
							)values("
						. $this->vid . ", "
						. "'" . _DEFAULT_COUNTRY_ID . "', "
						. $diagnostic_test['id'] . ", "
						. "UNIX_TIMESTAMP() )";
				
				$bRV = $bRV && $con->execute( $sql );
			}
		}


		// inserting procedures into database
		if ( is_array( $this->procedures ) && empty( $this->procedures ) == false ) {
			foreach ( $this->procedures as $procedure ) {

				$sql = "INSERT INTO visit_procedures
							(
							vid,
							country_id,
							id,
							created
							)values("
						. $this->vid . ", "
						. "'" . _DEFAULT_COUNTRY_ID . "', "
						. $procedure['id'] . ", "
						. "UNIX_TIMESTAMP() )";
				
				$bRV = $bRV && $con->execute( $sql );
			}
		}


		if ( $bRV == true ) {
			$con->commit();
		} else {
			$con->rollback();
		}

		$con->close();
		return $bRV;
	}

	public function update() {
		$rv = true;

		// create a connection object
		$con = new Connection();

		// Update visit head
		$sql = "UPDATE visit set "
				. "pid = " . $this->pid . ", "
				. "oid = " . $this->oid . ", "
				. "reason_id = " . $this->reason_id . ", "
				. "diagnosis_id = " . $this->diagnosis_id . ", "
				. "teaser = '" . $this->teaser . "', "
				. "status_id = '" . $this->status_id . "', "
				. "type_id = '" . $this->type_id . "', "
				. "modified = " . time() . " "
				. "WHERE vid = " . $this->vid;


		$rv = $rv && $con->execute( $sql );

		// Notes
		// check if there is any new note and insert into database
		foreach ( $this->notes as $note ) {
			if ( empty( $note['nid'] ) == true && empty( $note['title'] )== false && empty( $note['text'] ) == false ) {
				$sql = "INSERT into visit_notes 
											(
											nid,
											vid,
											uid,
											title,
											text,
											created
											)values("
						. "null, "
						. "'" . $this->vid . "', "
						. "'" . $this->uid . "', "
						. "'" . $note['title'] . "', "
						. "'" . $note['text'] . "', "
						. "UNIX_TIMESTAMP()"
						. ")";

				$rv = $rv && $con->execute( $sql );
			}
		}
		

		// Drugs:
		// for each drug in array check if there is a new drug prescrption and insert into database 
		foreach ( $this->drugs as $drug ) {
			if( Connection::entity_row_exists( 'visit_drugs', array('vid' => $this->vid, 'did' => $drug['did'], 'country_id' => _DEFAULT_COUNTRY_ID ) ) == false ){
				$sql = "INSERT into visit_drugs(
												vid,
												country_id,
												did,
												qty,
												created
												)values("
													. "'" . $this->vid . "', "
													. "'" . _DEFAULT_COUNTRY_ID . "', "
													. "'" . $drug['did'] . "', "
													. "'" . $drug['qty'] . "', "
													. "UNIX_TIMESTAMP()"
											. ")";
				$rv = $rv && $con->execute( $sql );
			}
		}
		
		
		
		// Diagnostic test:
		// check if there is a new drug prescrption and insert into database 
		foreach ( $this->diagnostic_tests as $diagnostic_test ) {
			// a record does NOT exists and so insert into database table
			if ( Connection::entity_row_exists( 'visit_diagnostic_tests', array('vid' => $this->vid, 'id' => $diagnostic_test['id'], 'country_id' => _DEFAULT_COUNTRY_ID ) ) == false ) {
				$sql = "INSERT into visit_diagnostic_tests(
													vid,
                                                    country_id,
                                                    id,
                                                    created
                                                    )values("
														. "'" . $this->vid . "', "
														. "'" . _DEFAULT_COUNTRY_ID . "', "
														. "'" . $diagnostic_test['id'] . "', "
														. "UNIX_TIMESTAMP()"
												. ")";
				$rv = $rv && $con->execute( $sql );
			}
		}

		// Procedures:
		// check if there is a new drug prescrption and insert into database 
		foreach ( $this->procedures as $procedure ) {
			// a record does NOT exists and so insert into database table
			if ( Connection::entity_row_exists( 'visit_procedures', array('vid' => $this->vid, 'id' => $procedure['id'], 'country_id' => _DEFAULT_COUNTRY_ID ) ) == false ) {
				$sql = "INSERT into visit_procedures(
													vid,
													country_id,
													id,
													created
													)values("
						. "'" . $this->vid . "', "
						. "'" . _DEFAULT_COUNTRY_ID . "', "
						. "'" . $procedure['id'] . "', "
						. "UNIX_TIMESTAMP()"
						. ")";
				$rv = $rv && $con->execute( $sql );
			}
		}

		if ( $rv === true ) {
			$con->commit();
		} else {
			Watchdog::write( Watchdog::TYPE_DATABASE, $con->sqlstate . ': ' . $con->sql, 0, Watchdog::WATCHDOG_WARNING );
			$con->rollback();
		}
	}
	
	
	
	public function delete(){
		if( self::exists( $this->vid ) == true){
			$this->status_id = '0';
			return $this->update();
		}else{
			return false;
		}
		
	}
	
	static function exists( $vid ){
		$visit = new Visit( $vid );
		if( empty( $visit->vid ) == true ){
			return false;
		}else{
			return true;
		}
	}

}
