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

import paraselene.*;
import paraselene.tag.*;
import java.util.*;

/**
 * ラジオボタングループ。<br>
 * このクラスはページへ所属しませんが、管理下のラジオボタンがページへ所属していれば、
 * クッキーへの入出力が可能です。
 */
public class RadioGroup extends Control implements VirtualTag {
	private static final long serialVersionUID = 2L;
	private Form	form = null;
	private ArrayList<CheckBox>	radio = new ArrayList<CheckBox>();

	/**
	 * コンストラクタ。
	 */
	public RadioGroup() {
		super( "radiogroup", false );
	}

	/**
	 * コンストラクタ。
	 * 引数で指定されたもののうち、ラジオボタンでないものは無視されます。
	 * 異なるフォームにあるラジオボタンも無視されます。
	 * @param tag グループ管理するラジオボタン。
	 */
	public RadioGroup( Tag ... tag ) {
		this();
		addCheckBox( tag );
	}

	protected Tag newReplica() {
		return copy4Replica( new RadioGroup() );
	}

	/**
	 * 管理ラジオボタンの追加。<br>
	 * 引数で指定されたもののうち、ラジオボタンでないものは無視されます。<br>
	 * 異なるフォームにあるラジオボタンも無視されます。<br>
	 * 別のラジオグループに属しているラジオボタンを渡すと、管理を移管します。
	 * @param tag グループ管理するラジオボタン。
	 */
	public void addCheckBox( Tag ... tag ) {
		for ( int i = 0; i < tag.length; i++ ) {
			if ( !(tag[i] instanceof CheckBox) )	continue;
			CheckBox	cb = (CheckBox)tag[i];
			if ( !cb.isRadio() )	continue;
			if ( form == null ) {
				form = cb.getForm();
			}
			else if ( form != cb.getForm() )	continue;
			RadioGroup	r = cb.getRadioGroup();
			if ( r != null ) {
				r.removeCheckBox( cb );
			}
			radio.add( cb );
			cb.setRadioGroup( this );
		}
	}

	/**
	 * 管理ラジオボタンの削除。
	 * @param tag グループ管理から除外するラジオボタン。
	 */
	public void removeCheckBox( Tag ... tag ) {
		for ( int i = 0; i < tag.length; i++ ) {
			int	cnt = radio.size();
			for ( int j = 0; j < cnt; j++ ) {
				CheckBox	cb = radio.get( j );
				if ( cb == tag[i] ) {
					radio.remove( j );
					cb.setRadioGroup( null );
					break;
				}
			}
		}
	}

	public Form getForm() {
		if ( form != null )	return form;
		int	cnt = radio.size();
		if ( cnt == 0 )	return null;
		form = radio.get( 0 ).getForm();
		return form;
	}

	public Page getAssignedPage() {
		int	cnt = radio.size();
		if ( cnt == 0 )	return super.getAssignedPage();
		return radio.get( 0 ).getAssignedPage();
	}

	/**
	 * 管理下のラジオボタンを返します。
	 * @return 管理下のラジオボタン。
	 */
	public CheckBox[] getCheckBox() {
		return radio.toArray( new CheckBox[0] );
	}

	/**
	 * 管理下のラジオボタンの name属性を指定のものに変更します。
	 * 該当ラジオボタンをページへ所属させる前にリネームして下さい。
	 * @param name name属性。
	 */
	public void rename( String name ) {
		CheckBox[]	cb = getCheckBox();
		for ( int i = 0; i < cb.length; i++ ) {
			cb[i].setAttribute( new Attribute( "name", name ) );
		}
	}

	/**
	 * 管理下のラジオボタンが全て無効であるか？
	 * @return true:全て無効、false:全てまたは一部が有効。
	 */
	public boolean isDisabled() {
		CheckBox[]	cb = getCheckBox();
		for ( int i = 0; i < cb.length; i++ ) {
			if ( cb[i].isDisabled() )	return false;
		}
		return true;
	}

	/**
	 * 管理下のラジオボタンの無効状態を一括変更します。
	 * @param flag true:無効、false:有効。
	 */
	public void setDisabled( boolean flag ) {
		CheckBox[]	cb = getCheckBox();
		for ( int i = 0; i < cb.length; i++ ) {
			cb[i].setDisabled( flag );
		}
	}

	/**
	 * 管理下のラジオボタンのうち、選択されているものの設定値を返します。
	 * @return 設定値。選択されていなければ null。
	 */
	public String getValueString() {
		return CheckBox.getRadio( getCheckBox() );
	}

	/**
	 * 管理下のラジオボタンで指定された設定値を持つものを選択状態にします。
	 * @param v 設定値。
	 */
	public void setValueString( String v ) {
		CheckBox.setRadio( getCheckBox(), v );
	}
}

