<?php
class GCE_Feed{
	private $feed_id = 1;
	private $feed_title = '';
	private $feed_url = '';
	private $max_events = 25;
	private $cache_duration = 43200;
	private $date_format = '';
	private $time_format = '';
	private $timezone = '';
	private $display_opts = array();
	private $multi_day = false;
	private $feed_start = 0;
	private $feed_end = 2145916800;
	private $use_builder = true;
	private $builder = '';
	private $events = array();
	private $error = false;

	function init(){
		require_once 'gce-event.php';

		//Break the feed URL up into its parts (scheme, host, path, query)
		$url_parts = parse_url($this->feed_url);

		$scheme_and_host = $url_parts['scheme'] . '://' . $url_parts['host'];

		//Remove the exisitng projection from the path, and replace it with '/full-noattendees'
		$path = substr($url_parts['path'], 0, strrpos($url_parts['path'], '/')) . '/full-noattendees';

		//Add the default parameters to the querystring (retrieving JSON, not XML)
		$query = '?alt=json&sortorder=ascending&orderby=starttime&singleevents=true';

		//Append the feed specific parameters to the querystring
		$query .= '&start-min=' . date('Y-m-d\TH:i:s', $this->feed_start);
		$query .= '&start-max=' . date('Y-m-d\TH:i:s', $this->feed_end);
		$query .= '&max-results=' . $this->max_events;
		if($this->timezone != '') $query .= '&ctz=' . $this->timezone;

		//If enabled, use experimental 'fields' parameter of Google Data API, so that only necessary data is retrieved. This *significantly* reduces amount of data to retrieve and process
		$general_options = get_option(GCE_GENERAL_OPTIONS_NAME);
		if($general_options['fields'] == true) $query .= '&fields=entry(title,link[@rel="alternate"],content,gd:where,gd:when)';

		//Put the URL back together
		$url = $scheme_and_host . $path . $query;

		//Attempt to retrieve the cached feed data
		$this->events = get_transient('gce_feed_' . $this->feed_id);

		//If the cached feed data isn't valid any more (has expired), or the URL has changed (settings have changed), then the feed data needs to be retrieved and decoded again
		if($this->events === false || get_transient('gce_feed_' . $this->feed_id . '_url') != $url){
			$this->events = array();

			//Retrieve the feed data
			$raw_data = wp_remote_get($url, array(
				'sslverify' => false, //sslverify is set to false to ensure https URLs work reliably. Data source is Google's servers, so is trustworthy
				'timeout' => 10       //Increase timeout from the default 5 seconds to ensure even large feeds are retrieved successfully
			));

			//If $raw_data is a WP_Error, something went wrong
			if(!is_wp_error($raw_data)){
				//If response code isn't 200, something went wrong
				if($raw_data['response']['code'] == 200){
					//Attempt to convert the returned JSON into an array
					$raw_data = json_decode($raw_data['body'], true);

					//If decoding was successful
					if(!empty($raw_data)){
						//If there are some entries (events) to process
						if(isset($raw_data['feed']['entry'])){
							//Loop through each event, extracting the relevant information
							foreach($raw_data['feed']['entry'] as $event){
								$title = (string)$event['title']['$t'];
								$description = (string)$event['content']['$t'];
								$link = (string)$event['link'][0]['href'];
								$location = (string)$event['gd$where'][0]['valueString'];
								$start_time = strtotime($event['gd$when'][0]['startTime']);
								$end_time = strtotime($event['gd$when'][0]['endTime']);

								//Create a GCE_Event using the above data. Add it to the array of events
								$this->events[] = new GCE_Event($title, $description, $location, $start_time, $end_time, $link);
							}

							//Cache the feed data
							set_transient('gce_feed_' . $this->feed_id, $this->events, $this->cache_duration);
							set_transient('gce_feed_' . $this->feed_id . '_url', $url, $this->cache_duration);
						}
					}else{
						//json_decode failed
						$this->error = __('Some data was retrieved, but could not be parsed successfully. Please ensure your feed URL is correct.', GCE_TEXT_DOMAIN);
					}
				}else{
					//The response code wasn't 200, so generate a helpful(ish) error message depending on error code 
					switch($raw_data['response']['code']){
						case 404:
							$this->error = __('The feed could not be found (404). Please ensure your feed URL is correct.', GCE_TEXT_DOMAIN);
							break;
						case 403:
							$this->error = __('Access to this feed was denied (403). Please ensure you have public sharing enabled for your calendar.', GCE_TEXT_DOMAIN);
							break;
						default:
							$this->error = sprintf(__('The feed data could not be retrieved. Error code: %s. Please ensure your feed URL is correct.', GCE_TEXT_DOMAIN), $raw_data['response']['code']);
					}
				}
			}else{
				//Generate an error message from the returned WP_Error
				$this->error = $raw_data->get_error_message() . ' Please ensure your feed URL is correct.';
			}
		}

		//Makes sure each event knows it came from this feed
		foreach($this->events as $event){
			$event->set_feed($this);
		}
	}

	//Return error message, or false if no error occurred
	function error(){
		return $this->error;
	}

	//Setters

	function set_feed_id($v){
		$this->feed_id = $v;
	}

	function set_feed_title($v){
		$this->feed_title = $v;
	}

	function set_feed_url($v){
		$this->feed_url = $v;
	}

	function set_max_events($v){
		$this->max_events = $v;
	}

	function set_cache_duration($v){
		$this->cache_duration = $v;
	}

	function set_date_format($v){
		$this->date_format = $v;
	}

	function set_time_format($v){
		$this->time_format = $v;
	}

	function set_timezone($v){
		$this->timezone = $v;
	}

	function set_display_options($v){
		$this->display_opts = $v;
	}

	function set_multi_day($v){
		$this->multi_day = $v;
	}

	function set_feed_start($v){
		$this->feed_start = $v;
	}

	function set_feed_end($v){
		$this->feed_end = $v;
	}

	function set_use_builder($v){
		$this->use_builder = $v;
	}

	function set_builder($v){
		$this->builder = $v;
	}

	//Getters

	function get_events(){
		return $this->events;
	}

	function get_feed_id(){
		return $this->feed_id;
	}

	function get_feed_title(){
		return $this->feed_title;
	}

	function get_date_format(){
		return $this->date_format;
	}

	function get_time_format(){
		return $this->time_format;
	}

	function get_display_options(){
		return $this->display_opts;
	}

	function get_multi_day(){
		return $this->multi_day;
	}

	function get_feed_start(){
		return $this->feed_start;
	}

	function get_feed_end(){
		return $this->feed_end;
	}

	function get_timezone(){
		return $this->timezone;
	}

	function get_use_builder(){
		return $this->use_builder;
	}

	function get_builder(){
		return $this->builder;
	}
}
?>