<?php
/**
* HTMLフォームオブジェクトのファクトリクラス
*
* PHP version 5
*
* @package    core
* @author     stk2k <stk2k@sazysoft.com>
* @copyright  2008 stk2k, sazysoft
*/

class charcoal_HTMLFormFactory
{
	private $_form_model;

	/*
	 *	フォームオブジェクトを作成する
	 */
	private static function _createForm( charcoal_IFormModel $model, $id )
	{
		// フォームオブジェクトを作成
		$action  = $model->getFormAnnotationValue( 'action' );
		$method  = $model->getFormAnnotationValue( 'method' );
		$target  = $model->getFormAnnotationValue( 'target' );
		$class   = $model->getFormAnnotationValue( 'class' );
		$style   = $model->getFormAnnotationValue( 'style' );

		$attributes = array();
		$attributes['id'] = ++$id;
		$attributes['action'] = $action;
		$attributes['method'] = $method;
		$attributes['target'] = $target;
		$attributes['class'] = $class;
		$attributes['style'] = $style;

		$form = new charcoal_HTMLFormObject( $attributes );

		return $form;
	}

	/*
	 *	パネルを作成する
	 */
	private static function _createPanel( charcoal_IFormModel $model, $id, $panel_name )
	{
		$layout  = $model->getAnnotationValue( $panel_name, 'layout' );
		$class   = $model->getAnnotationValue( $panel_name, 'class' );
		$style   = $model->getAnnotationValue( $panel_name, 'style' );

		$attributes = array();
		$attributes['id'] = ++$id;
		$attributes['class'] = $class;
		$attributes['style'] = $style;

		$panel = new charcoal_HTMLPanelObject( s($layout), $attributes );

		return $panel;
	}

	/*
	 *	キャプションを作成する
	 */
	private static function _createCaption( charcoal_IFormModel $model, $id, $field, $caption, charcoal_HTMLPanelObject $panel )
	{
		$default_caption_class = $model->getDefaultCaptionClass();
		$default_caption_style = $model->getDefaultCaptionStyle();
		$class = $model->getAnnotationValue( $field, 'caption_class' );
		$style = $model->getAnnotationValue( $field, 'caption_style' );

		$attributes = array();
		$attributes['id'] = ++$id;
		$attributes['class'] = $class ? $class : $default_caption_class;
		$attributes['style'] = $style ? $style : $default_caption_style;

		$text = new charcoal_HTMLTextObject( s($caption), $attributes );

		if ( $text ){
			$panel->addChild( $text );
		}
	}

	/*
	 *	入力フィールドを作成する
	 */
	private static function _createInputField( charcoal_IFormModel $model, $id, $field, charcoal_DTO $dto, charcoal_HTMLPanelObject $panel )
	{
		// 入力タイプ
		$type = $model->getAnnotationValue( $field, 'input_type' );
		if ( !$type ){
			// 入力タイプは必須
			return NULL;
		}

		$disabled = $model->getAnnotation( $field, 'disabled' );

		$default_field_class = $model->getDefaultFieldClass($type);
		$default_field_style = $model->getDefaultFieldStyle($type);
		$class = $model->getAnnotationValue( $field, 'class' );
		$style = $model->getAnnotationValue( $field, 'style' );
		$value = $model->getAnnotationValue( $field, 'value' );

		$attributes = array();
		$attributes['id'] = ++$id;
		$attributes['type'] = $type;
		$attributes['name'] = $field;
		$attributes['class'] = $class ? $class : $default_field_class;
		$attributes['style'] = $style ? $style : $default_field_style;
		$attributes['disabled'] = $disabled ? 'disabled' : NULL;

		if ( $value === '%DTO_VALUE%' ){
			$value = $dto->$field;
		}

		$input = NULL;

		switch ( $type ){
		case 'text':
		case 'password':
			$size = $model->getAnnotationValue( $field, 'size' );
			$attributes['value'] = $value;
			$attributes['size'] = $size;
			$input = new charcoal_HTMLInputObject( $attributes );
			break;
		case 'submit':
		case 'reset':
			$attributes['value'] = $value;
			$input = new charcoal_HTMLInputObject( $attributes );
			break;
		case 'textarea':
			$cols = $model->getAnnotationValue( $field, 'cols' );
			$rows = $model->getAnnotationValue( $field, 'rows' );
			$attributes['cols'] = $cols;
			$attributes['rows'] = $rows;
			$text = nl2br($value);
			$input = new charcoal_HTMLTextAreaObject( s($text), $attributes );
			break;
		case 'radio':
		case 'checkbox':
			$choice_list_name = $model->getAnnotationValue( $field, 'choice_list' );
			$choice_list = $model->getChoiceList( $choice_list_name );

			$attributes['value'] = $value;
			$attributes['name'] = $field . '[]';

			$checked = $model->getAnnotationValue( $field, 'checked' );
			$check_status = $checked ? explode( ',', $checked ) : NULL;
			$class = $model->getAnnotationValue( $field, 'choice_caption_class' );
			$style = $model->getAnnotationValue( $field, 'choice_caption_style' );

			$caption_attributes = array();
			$caption_attributes['id'] = ++$id;
			$caption_attributes['class'] = $class ? $class : NULL;
			$caption_attributes['style'] = $style ? $style : NULL;

			$input = new charcoal_HTMLChoiceGroupObject( $attributes, $caption_attributes, $choice_list, $check_status );
			break;
		case 'select':
			$choice_list_name = $model->getAnnotationValue( $field, 'choice_list' );
			$choice_list = $model->getChoiceList( $choice_list_name );
			$input = new charcoal_HTMLSelectObject( $attributes, $choice_list, $value );
			break;
		}

		if ( $input ){
			$panel->addChild( $input );
		}
	}

	/*
	 *	読み取り専用フィールドを作成する
	 */
	private static function _createStaticField( charcoal_IFormModel $model, $id, $field, charcoal_DTO $dto, charcoal_HTMLPanelObject $panel )
	{
		// 入力タイプ
		$type = $model->getAnnotationValue( $field, 'input_type' );
		if ( !$type ){
			// 入力タイプは必須
			return NULL;
		}

		$default_field_class = $model->getDefaultFieldClass($type);
		$default_field_style = $model->getDefaultFieldStyle($type);
		$class = $model->getAnnotationValue( $field, 'class' );
		$style = $model->getAnnotationValue( $field, 'style' );
		$value = $model->getAnnotationValue( $field, 'value' );

		$attributes = array();
		$attributes['id'] = ++$id;
		$attributes['type'] = $type;
		$attributes['name'] = $field;
		$attributes['class'] = $class ? $class : $default_field_class;
		$attributes['style'] = $style ? $style : $default_field_style;

		if ( $value === '%DTO_VALUE%' ){
			$value = $dto->$field;
		}

		$input = NULL;

		switch ( $type ){
		case 'text':
		case 'password':
			$attributes['class'] = NULL;
			$attributes['style'] = NULL;
			$input = new charcoal_HTMLTextObject( s($value), $attributes );
			break;
		case 'submit':
		case 'reset':
			$input = NULL;
			break;
		case 'textarea':
			$attributes['class'] = NULL;
			$attributes['style'] = NULL;
			$text = nl2br($value);
			$input = new charcoal_HTMLTextObject( s($text), $attributes );
			break;
		case 'radio':
		case 'checkbox':
			$choice_list_name = $model->getAnnotationValue( $field, 'choice_list' );
			$choice_list = $model->getChoiceList( $choice_list_name );
			if ( is_array($value) ){
				$caption =NULL;
				foreach( $value as $choice ){
					if ( isset($choice_list[$choice]) ){
						if ( $caption ){
							$caption .= ',&nbsp;';
						}
						$caption .= $choice_list[$choice];
					}
				}
				$input = new charcoal_HTMLTextObject( s($caption), $attributes );
			}
			break;
		case 'select':
			$choice_list_name = $model->getAnnotationValue( $field, 'choice_list' );
			$choice_list = $model->getChoiceList( $choice_list_name );
			$caption = isset($choice_list[$value]) ? $choice_list[$value] : NULL;
			$attributes['class'] = NULL;
			$attributes['style'] = NULL;
			$input = new charcoal_HTMLTextObject( s($caption), $attributes );
			break;
		}

		if ( $input ){
			$panel->addChild( $input );
		}
	}

	/*
	 *	非表示フィールドを作成する
	 */
	private static function _createHiddenField( charcoal_IFormModel $model, $id, $field, charcoal_DTO $dto, charcoal_HTMLPanelObject $panel )
	{
		$value = $model->getAnnotationValue( $field, 'value' );

		if ( $value === '%DTO_VALUE%' ){
			$value = $dto->$field;
		}

		$attributes = array();
		$attributes['id'] = ++$id;
		$attributes['type'] = 'hidden';
		$attributes['name'] = $field;
		$attributes['value'] = $value;

		$input = new charcoal_HTMLInputObject( $attributes );

		$panel->addChild( $input );
	}

	/*
	 *	フォームを作成
	 */
	public static function create( charcoal_IFormModel $model, charcoal_DTO $dto, $read_only = FALSE )
	{
		// 要素ID
		$id = 0;

		// フォームオブジェクトを作成
		$form = self::_createForm( $model, $id );

		// 入力コントロールを追加
		$input_list = $model->getInputList();
		if ( $input_list ){

			$form_panels = array();

			foreach( $input_list as $field ){

				// パネルを取得
				$panel_name = $model->getAnnotationValue( $field, 'panel' );
				if ( !$panel_name ){
					// パネルは必須
					continue;
				}
				if ( !isset($form_panels[$panel_name]) ){
					// なければ作る
					$panel = self::_createPanel( $model, $id, $panel_name );
					$form_panels[$panel_name] = $panel;
					$form->addChild( $panel );
				}
				else{
					$panel = $form_panels[$panel_name];
				}

				// キャプション
				$caption = $model->getAnnotationValue( $field, 'caption' );
				if ( $caption ){
					self::_createCaption( $model, $id, $field, $caption, $panel );
				}

				// 入力フィールド
				$read_only_field = $model->getAnnotation( $field, 'read_only' );

				if ( $read_only || ($read_only_field !== NULL) ){
					self::_createStaticField( $model, $id, $field, $dto, $panel );
					self::_createHiddenField( $model, $id, $field, $dto, $panel );
				}
				else{
					self::_createInputField( $model, $id, $field, $dto, $panel );
				}
			}
		}

		return $form;
	}

}
