<?php
	//very simple access-only coordinate class
	//great for latitude/longitude pairs
	class Coordinate {
		private $longitude;
		private $latitude;
		
		public function __construct($longitude, $latitude) {
			$this->longitude = $longitude;
			$this->latitude = $latitude;
		}
		
		public function getLongitude() {
			return $this->longitude;
		}
		
		public function getLatitude() {
			return $this->latitude;
		}
		
		public function __toString() {
			return '(' . $this->longitude . ', ' . $this->latitude . ')';
		}
	}
	
	//this class represents the data from one of the states in the population ZCTA database
	//for now, I'm ignoring the boundary table
	class StatePopulationZCTA {
		const MULTI_STATE = 'MULTI-STATE';

		private static $radianToDegreeRatio;
	
		private $state;
		private $statePopulation;
		private $zctaToPopulation;
		private $zctaToCentroid;

		public static function init() {
			self::$radianToDegreeRatio = 180 / pi();
		}
		
		public function __construct($populationDB, $state) {
			$this->state = $state;
			$this->statePopulation = 0;
			$this->zctaToPopulation = array();
			$this->zctaToCentroid = array();

			$sqliteDB = new SQLite3($populationDB);

			//get state population
			if($this->isMultiState())
				$statePopulation = PHP_INT_MAX;
			else {
				$statePopulation = $sqliteDB->query("SELECT population_total FROM states WHERE state = '$state';");
				$statePopulation = $statePopulation->fetchArray();
				$this->statePopulation = $statePopulation['population_total'];
			}

			//get ZCTA populations
			if($this->isMultiState()) {
				$zctasPopulations = $sqliteDB->query("SELECT zcta, population_total, centroid_longitude, centroid_latitude FROM zctas;");
				while($zctaPopulation = $zctasPopulations->fetchArray()) { 
					$zcta = $zctaPopulation['zcta'];
					$population = $zctaPopulation['population_total'];
					$this->zctaToPopulation[$zcta] = $population;

					$centroidLongitude = $zctaCentroid['centroid_longitude'];
					$centroidLatitude = $zctaCentroid['centroid_latitude'];
					$centroid = new Coordinate($centroidLongitude, $centroidLatitude);
					$this->zctaToCentroid[$zcta] = $centroid;
				}
			} else {
				$zctasPopulations = $sqliteDB->query("SELECT zctas.zcta, zctas.population_total, zctas.centroid_longitude, zctas.centroid_latitude FROM zctas, states INNER JOIN states_zctas ON states_zctas.zcta_id=zctas.id AND states_zctas.state_id=states.id WHERE states.state='$state';");
				var_dump($zctasPopulations);
				while($zctaPopulation = $zctasPopulations->fetchArray()) {
					$zcta = $zctaPopulation['zcta'];
					$population = $zctaPopulation['population_total'];
					$this->zctaToPopulation[$zcta] = $population;

					$centroidLongitude = $zctaPopulation['centroid_longitude'];
					$centroidLatitude = $zctaPopulation['centroid_latitude'];
					$centroid = new Coordinate($centroidLongitude, $centroidLatitude);
					$this->zctaToCentroid[$zcta] = $centroid;
				}
			}
		}

		public function containsZCTA($zcta) {
			return array_key_exists($zcta, $this->zctaToPopulation);
		}
		
		public function isMultiState() {
			return $this->state == self::MULTI_STATE;
		}
		
		public function getState() {
			return $this->state;
		}
		
		public function getStatePopulation() {
			return $this->statePopulation;
		}
		
		public function getZCTAPopulation($zcta) {
			return $this->zctaToPopulation[$zcta];
		}
		
		public function getZCTACentroid($zcta) {
			return $this->zctaToCentroid[$zcta];
		}
		
		public function getZCTAs() {
			return array_keys($this->zctaToPopulation);
		}
		
		public function getZCTAToPopulation() {
			return $this->zctaToPopulation;
		}

		//get an array containing all ZCTAs within the specified radius of the specified ZCTA
		public function getZCTAsWithinRadius($zcta, $radius) {
			$zctasWithinRadius = array();
			$zctaCentroid = $this->getZCTACentroid($zcta);
			$zctas = $this->getZCTAs();
			foreach($zctas as $comparisonZCTA) {
				$comparisonZCTACentroid = $this->getZCTACentroid($comparisonZCTA);
				if($this->getDistance($zctaCentroid, $comparisonZCTACentroid) <= $radius)
					array_push($zctasWithinRadius, $comparisonZCTA);
			}
			return $zctasWithinRadius;
		}
		
		//get the total population count for an array of ZCTAs
		public function getTotalPopulation($zctas) {
			$totalPopulation = 0;
			foreach($zctas as $zcta)
				$totalPopulation += $this->getZCTAPopulation($zcta);
			return $totalPopulation;
		}
		
		//get the distance between 2 centroids (in miles)
		//this formula comes from http://www.meridianworlddata.com/Distance-Calculation.asp
		public function getDistance($centroid1, $centroid2) {
			if (is_null($centroid1) || is_null($centroid2))
				return 2147483647;
			
			//coordinates in the KML are given as longitude,latitude (example: -94.662628,41.488831)
			$latitude1 = ($centroid1->getLatitude()) / self::$radianToDegreeRatio;
			$longitude1 = ($centroid1->getLongitude()) / self::$radianToDegreeRatio;
			$latitude2 = ($centroid2->getLatitude()) / self::$radianToDegreeRatio;
			$longitude2 = ($centroid2->getLongitude()) / self::$radianToDegreeRatio;
			
			return 3963 * acos(sin($latitude1) * sin($latitude2) + cos($latitude1) * cos($latitude2) * cos($longitude2 - $longitude1));
		}
	}
	StatePopulationZCTA::init();
?>
