<?php

namespace Louis1021\ICalendar\helpers;

use ArrayAccess;
use ArrayIterator;
use Countable;
use IteratorAggregate;

/**
 * A class for storing a single (complete) line of the iCal file.
 * Will find the line-type, the arguments and the data of the file and
 * store them.
 *
 * The line-type can be found by querying getIdent(), data via either
 * getData() or typecasting to a string.
 * Params can be access via the ArrayAccess. A iterator is also avilable
 * to iterator over the params.
 *
 * @package SG_iCalReader
 * @author Morten Fangel (C) 2008
 * @license http://creativecommons.org/licenses/by-sa/2.5/dk/deed.en_GB CC-BY-SA-DK
 */
class SG_iCal_Line implements ArrayAccess, Countable, IteratorAggregate {
	protected $ident;
	protected $data;
	protected $params = array();

	protected $replacements = array('from'=>array('\\,', '\\n', '\\;', '\\:', '\\"'), 'to'=>array(',', "\n", ';', ':', '"'));

	/**
	 * Constructs a new line.
	 */
	public function __construct( $line ) {
		$split = strpos($line, ':');
		$idents = explode(';', substr($line, 0, $split));
		$ident = strtolower(array_shift($idents));

		$data = trim(substr($line, $split+1));
		$data = str_replace($this->replacements['from'], $this->replacements['to'], $data);

		$params = array();
		foreach( $idents AS $v) {
			list($k, $v) = explode('=', $v);
			$params[ strtolower($k) ] = $v;
		}

		$this->ident = $ident;
		$this->params = $params;
		$this->data = $data;
	}

	/**
	 * Is this line the begining of a new block?
	 * @return bool
	 */
	public function isBegin() {
		return $this->ident == 'begin';
	}

	/**
	 * Is this line the end of a block?
	 * @return bool
	 */
	public function isEnd() {
		return $this->ident == 'end';
	}

	/**
	 * Returns the line-type (ident) of the line
	 * @return string
	 */
	public function getIdent() {
		return $this->ident;
	}

	/**
	 * Returns the content of the line
	 * @return string
	 */
	public function getData() {
		return $this->data;
	}

	/**
	 * Returns the content of the line
	 * @return string
	 */
	public function getDataAsArray() {
		if (strpos($this->data,",") !== false) {
			return explode(",",$this->data);
		}
		else
			return array($this->data);
	}

	/**
	 * A static helper to get a array of SG_iCal_Line's, and calls
	 * getData() on each of them to lay the data "bare"..
	 *
	 * @param SG_iCal_Line[]
	 * @return array
	 */
	public static function Remove_Line($arr) {
		$rtn = array();
		foreach( $arr AS $k => $v ) {
			if(is_array($v)) {
				$rtn[$k] = self::Remove_Line($v);
			} elseif( $v instanceof SG_iCal_Line ) {
				$rtn[$k] = $v->getData();
			} else {
				$rtn[$k] = $v;
			}
		}
		return $rtn;
	}

	/**
	 * @see ArrayAccess.offsetExists
	 */
	public function offsetExists( $param ) {
		return isset($this->params[ strtolower($param) ]);
	}

	/**
	 * @see ArrayAccess.offsetGet
	 */
	public function offsetGet( $param ) {
		$index = strtolower($param);
		if (isset($this->params[ $index ])) {
			return $this->params[ $index ];
		}
	}

	/**
	 * Disabled ArrayAccess requirement
	 * @see ArrayAccess.offsetSet
	 */
	public function offsetSet( $param, $val ) {
		return false;
	}

	/**
	 * Disabled ArrayAccess requirement
	 * @see ArrayAccess.offsetUnset
	 */
	public function offsetUnset( $param ) {
		return false;
	}

	/**
	 * toString method.
	 * @see getData()
	 */
	public function __toString() {
		return $this->getData();
	}

	/**
	 * @see Countable.count
	 */
	public function count() {
		return count($this->params);
	}

	/**
	 * @see IteratorAggregate.getIterator
	 */
	public function getIterator() {
		return new ArrayIterator($this->params);
	}
}
