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

class HTMLFormFactory
{
	private $_form_model;

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

		// APP_URLを展開
		$app_url = Profile::getString( s('APP_URL') );
		$action = str_replace( '{APP_URL}', "$app_url", $action );

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

		$form = new HTMLFormObject( $attributes );

		return $form;
	}

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

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

		$panel = new HTMLPanelObject( $layout, $attributes );

		return $panel;
	}

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

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

		$text = new HTMLTextObject( $caption, $attributes );

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

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

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

		$default_field_class = $model->getDefaultFieldClass($type);
		$default_field_style = $model->getDefaultFieldStyle($type);
		$class = $model->getAnnotationValue( $field, s('class') );
		$style = $model->getAnnotationValue( $field, s('style') );
		$value = $model->getAnnotationValue( $field, s('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;

		$value = $value ? $value : $dto->getProperty( $field );

		$input = NULL;

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

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

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

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

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

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

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

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

		$id = $id->getValue() + 1;

		$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;

		$value = $dto->getProperty( $field );

		$input = NULL;

		switch ( "$type" ){
		case 'text':
		case 'password':
			$attributes['class'] = NULL;
			$attributes['style'] = NULL;
			$input = new HTMLTextObject( $value, $attributes );
			break;
		case 'submit':
		case 'reset':
			$input = NULL;
			break;
		case 'textarea':
			$attributes['class'] = NULL;
			$attributes['style'] = NULL;
			$text = nl2br($value);
			$input = new HTMLTextObject( $text, $attributes );
			break;
		case 'radio':
		case 'checkbox':
			$choice_list_name = $model->getAnnotationValue( $field, s('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 HTMLTextObject( $caption, $attributes );
			}
			break;
		case 'select':
			$choice_list_name = $model->getAnnotationValue( $field, s('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 HTMLTextObject( $caption, $attributes );
			break;
		}

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

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

		$value = $value ? $value : $dto->$field;

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

		$input = new HTMLInputObject( $attributes );

		$panel->addChild( $input );
	}

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


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

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

		if ( $input_list ){

			$form_panels = array();

			foreach( $input_list as $field ){

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

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

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

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

				$hidden  = $model->getAnnotation( s($field), s('hidden') );
				if ( $hidden !== NULL ){
					self::_createHiddenField( $model, $id++, $field, $dto, $panel );
				}
			}
		}

		return $form;
	}

}

return __FILE__;