/*
 * Paraselene
 * Copyright (c) 2009, 2010  Akira Terasaki
 * このファイルは同梱されているLicense.txtに定めた条件に同意できる場合にのみ
 * 利用可能です。
 */
package paraselene.tag.form;


import java.io.*;
import java.net.*;
import paraselene.*;
import paraselene.tag.*;

/**
 * チェックボックス(ラジオ型動作もあり)。
 */
public class CheckBox extends Input {
	private static final long serialVersionUID = 2L;
	class NameAttribute extends Attribute {
		private	boolean	flag = false;
		NameAttribute( String v ) {
			super( "name", v );
		}
		protected String getValueString( HTMLPart.StringMode mode ) {
			if ( flag ) {
				return Page.getIndexName( super.getValueString( mode ) );
			}
			return super.getValueString( mode );
		}
		public String toHtmlString( boolean xml ) {
			flag = true;
			String	ret = super.toHtmlString( xml );
			flag = false;
			return ret;
		}
	}

	private boolean radio_flag = false;
	private RadioGroup	radio = null;

	void setRadioGroup( RadioGroup r ) {
		radio = r;
	}

	/**
	 * 所属しているラジオグループを返す。
	 * @return 所属グループ。
	 */
	public RadioGroup getRadioGroup() {
		return radio;
	}

	/**
	 * コンストラクタ。
	 * @param radio_f true:ラジオ型、false:単一。
	 */
	public CheckBox( boolean radio_f ) {
		super( radio_f?	Input.Type.RADIO:	Input.Type.CHECK );
		radio_flag = radio_f;
	}

	protected Tag newReplica() {
		return copy4Replica( new CheckBox( radio_flag ) );
	}

	/**
	 * ラジオ動作であるか？
	 * @return true:ラジオ型、false:単一チェック型。
	 */
	public boolean isRadio() {
		return radio_flag;
	}

	public void setAttribute( Attribute at ) {
		if ( radio_flag ) {
			if ( "name".equals( at.getName() ) ) {
				at = new NameAttribute( at.getString() );
			}
		}
		super.setAttribute( at );
	}

	/**
	 * ラジオ型チェックの制御。
	 * @param form フォーム。
	 * @param name 名称。指定名のものが存在しなければ何もしない。
	 * @param val 値。nullなら全解除。
	 */
	public static void setRadio( Form form, String name, String val ) {
		name = Page.getIndexName( name );
		Control[]	tag = form.getAllControl( name );
		for ( int i = 0; i < tag.length; i++ ) {
			if ( !(tag[i] instanceof CheckBox) )	continue;
			CheckBox	box = (CheckBox)tag[i];
			if ( !box.radio_flag )	continue;
			if ( val == null ) {
				Control.Status.CHECKED.set( box, false );
			}
			else {
				Control.Status.CHECKED.set( box, val.equals( box.getValueString() ) );
			}
		}
	}

	/**
	 * ラジオ型チェックの設定値取得。
	 * @param form フォーム。
	 * @param name 名称。指定名のものが存在しなければ何もしない。
	 * @return 設定値。何も設定されていなければnull。
	 */
	public static String getRadio( Form form, String name ) {
		name = Page.getIndexName( name );
		Control[]	tag = form.getAllControl( name );
		for ( int i = 0; i < tag.length; i++ ) {
			if ( !(tag[i] instanceof CheckBox) )	continue;
			CheckBox	box = (CheckBox)tag[i];
			if ( !box.radio_flag )	continue;
			if ( box.isChecked() )	return box.getValueString();
		}
		return null;
	}

	/**
	 * ラジオ型チェックの制御。
	 * @param group チェックボックスの配列。
	 * チェックボックスでなければ無視されます。
	 * @param val 値。nullなら全解除。
	 */
	public static void setRadio( Tag[] group, String val ) {
		for ( int i = 0; i < group.length; i++ ) {
			if ( !(group[i] instanceof CheckBox) )	continue;
			CheckBox	box = (CheckBox)group[i];
			if ( !box.radio_flag )  continue;
			String	v = box.getValueString();
			boolean	flag = false;
			if ( v != null ) {
				flag = v.equals( val );
			}
			Control.Status.CHECKED.set( box, flag );
		}
	}

	/**
	 * ラジオ型チェックの設定値取得。
	 * @param group チェックボックスの配列。
	 * チェックボックスでなければ無視されます。
	 * @return 設定値。何も設定されていなければnull。
	 */
	public static String getRadio( Tag[] group ) {
		for ( int i = 0; i < group.length; i++ ) {
			if ( !(group[i] instanceof CheckBox) )  continue;
			CheckBox	box = (CheckBox)group[i];
			if ( !box.radio_flag )  continue;
			if ( box.isChecked() )  return box.getValueString();
		}
		return null;
	}

	/**
	 * 選択されているか？
	 * @return true:選択されている、false:選択されていない。
	 */
	public boolean isChecked() {
		return Control.Status.CHECKED.isSet( this );
	}

	/**
	 * チェック設定。
	 * ラジオ型であれば、HTML中の同一グループが切り替わります。
	 * @param flag true:チェックする、false:チェック解除する。
	 */
	public void setChecked( boolean flag ) {
		if ( radio_flag && flag ) {
			Tag[]	tag = getAssignedTag().getAssignedPage().getAllTagByType( "form" );
			for ( int i = 0; i < tag.length; i++ ) {
				if ( !(tag[i] instanceof Form) )	continue;
				Form	form = (Form)tag[i];
				if ( form.isContained( this ) ) {
					setRadio( form, getName(), getValueString() );
					break;
				}
			}
			return;
		}
		Control.Status.CHECKED.set( this, flag );
	}

}

