<?php

class Tag_Checkbox extends Tag
{
	const BITWISE = 0x1;
	const SINGLE = 0x2;
	const MULTIPLE = 0x3;

	protected $checkbox_type;
	protected $options;

	public function __construct($name=NULL,$options=NULL,$attributes=array(),$type=self::MULTIPLE)
	{
		parent::__construct('div', $attributes);
		$this->addClass('checkboxset');
		$this->attr('name',$name);
		$this->checkbox_type = $type;

		// Add all Options as Children
		if( is_array($options) && count($options) > 0 )
		{
			$i = 1;
			foreach($options as $key => $label)
			{
				$id = $name.'-option-'.$i;

				$input_tag = new Tag_Input($name.'[]');
				$input_tag->attr('type','checkbox');
				$input_tag->attr('value',$key);
				$input_tag->attr('id',$id);

				$label_tag = new Tag_Label;
				$label_tag->text($label);
				$label_tag->attr('for',$id);
				$label_tag->addClass('checkbox');

				$div_tag = new Tag('div');
				$div_tag->addChild($input_tag, $label_tag);
				$this->options[] = $input_tag;

				$this->addChild($div_tag);
				$i++;
			}
		}
	}

	public function attr($name, $value=NULL)
	{
		switch($name)
		{
			case 'value':
				return $this->value($value);
				break;

			default:
				return parent::attr($name,$value);
		}
	}

	public function value($value=NULL)
	{
		switch($this->checkbox_type)
		{
			case self::BITWISE:
				return $this->_value_bitwise($value);
				break;
			case self::SINGLE:
				return $this->_value_single($value);
				break;
			default: // MULTIPLE
				return $this->_value_array($value);
		}
	}//function

	/** Returns or Sets value of the checkbox when used a single value checkbox */
	protected function _value_single($value=NULL)
	{
		if( is_null($value) )
		{
			// Return the FIRST matching single value from the set of checked boxes
			foreach($this->options as $input)
			{
				if($input->attr('checked','checked'))
					return $input->attr('value');
			}
		}
		else
		{
			// Set value, checks on or off for all inputs
			foreach($this->options as $input)
			{
				if($input->attr('value') == $value)
					$input->attr('checked','checked');
				else
					$input->attr('checked','');
			}
		}
	}

	/** Returns or Sets values in the checkbox set using values provided in an array of values matching those in the options array */
	protected function _value_array($value=NULL)
	{
		if( is_null($value) )
		{
			// Retrieve all values selected and return in an array
			foreach($this->options as $option)
			{
				if( $option->attr('checked') == 'checked' )
					$values[] = $option->attr('value');
			}
			return $values;
		}
		else
		{
			// Set the provided values
			if( !is_array($value) )
				$value = array($value);

			foreach($value as $v)
			{
				foreach($this->options as $input)
				{
					if( $input->attr('value') == $v )
					{
						$input->attr('checked','checked');
						continue;
					}
				}
			}
		}
	}

	/** Returns or Sets values in the checkbox set using matching bitwise flag values in the provided value for the field */
	protected function _value_bitwise($value=NULL)
	{
		if( is_null($value) )
		{
			// Return the combined bitwise field value
			$flags = 0;
			foreach($this->options as $input)
			{
				if( $input->attr('checked') == 'checked' )
				{
					$flags = $flags | $input->attr('value');
				}
			}
			return $flags;
		}
		else
		{
			// Set the checkbox states based on the provided bitwise field value and options
			// NOTE: Options provided must include compatible bitwise values as keys
			if( !is_numeric($value) )
				$value = 0;
			else
				$value = (int)$value;

			// Un-check all checkboxes
			foreach($this->options as $input)
				$input->attr('checked','');

			// Set all inputs to "Checked" when their flag tests true against the provided bitwise field value
			foreach($this->options as $input)
			{
				if( $value & $input->attr('value') )
				{
					$input->attr('checked','checked');
					continue;
				}
			}
		}
	}

}
