package org.seasar.jsf.component;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.faces.component.UISelectItems;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;

import org.seasar.framework.beans.BeanDesc;
import org.seasar.framework.beans.PropertyDesc;
import org.seasar.framework.beans.factory.BeanDescFactory;

/**
 * @author higa
 *  
 */
public class UISelectItemsX extends UISelectItems {

	private String itemLabel_ = "label";

	private String itemValue_ = "value";
	
	private String nullLabel_;

	public String getItemLabel() {
		return itemLabel_;
	}

	public void setItemLabel(String itemLabel) {
		itemLabel_ = itemLabel;
	}

	public String getItemValue() {
		return itemValue_;
	}

	public void setItemValue(String itemValue) {
		itemValue_ = itemValue;
	}

	public String getNullLabel() {
		return nullLabel_;
	}

	public void setNullLabel(String nullLabel) {
		nullLabel_ = nullLabel;
	}
	
	/**
	 * @see javax.faces.component.UISelectItems#getValue()
	 */
	public Object getValue() {
		Object value = super.getValue();
		if (value instanceof SelectItem[] || value instanceof SelectItem) {
			return value;
		}
		List list = new ArrayList();
		if (nullLabel_ != null) {
			SelectItem si = new SelectItem();
			si.setLabel(nullLabel_);
			list.add(si);
		}
		if (value instanceof Collection) {
			for (Iterator it = ((Collection) value).iterator(); it.hasNext();) {
				Object item = it.next();
				if (item instanceof SelectItem) {
					list.add(item);
				} else if (item instanceof Map) {
					Map map = (Map) item;
					SelectItem si = new SelectItem();
					Object itemValueValue = map.get(itemValue_);
					if (itemValueValue != null) {
						si.setValue(itemValueValue);
					}
					Object itemLabelValue = map.get(itemLabel_);
					if (itemLabelValue == null) {
						itemLabelValue = itemValueValue;
					}
					if (itemLabelValue != null) {
						si.setLabel(itemLabelValue.toString());
					}
					list.add(si);
				} else {
					SelectItem si = new SelectItem();
					BeanDesc beanDesc = BeanDescFactory.getBeanDesc(item
							.getClass());
					PropertyDesc pd = beanDesc.getPropertyDesc(itemValue_);
					Object itemValueValue = pd.getValue(item);
					if (itemValueValue != null) {
						si.setValue(itemValueValue);
					}
					Object itemLabelValue = null;
					if (beanDesc.hasPropertyDesc(itemLabel_)) {
						pd = beanDesc.getPropertyDesc(itemLabel_);
						itemLabelValue = pd.getValue(item);
					}
					if (itemLabelValue == null) {
						itemLabelValue = itemValueValue;
					}
					if (itemLabelValue != null) {
						si.setLabel(itemLabelValue.toString());
					}
					list.add(si);
				}
			}
		} else if (value instanceof Map) {
			for (Iterator i = ((Map) value).entrySet().iterator(); i.hasNext();) {
				Map.Entry entry = (Map.Entry) i.next();
				SelectItem si = new SelectItem();
				Object itemValueValue = entry.getValue();
				if (itemValueValue != null) {
					si.setValue(itemValueValue);
				}
				Object itemLabelValue = entry.getKey();
				if (itemLabelValue == null) {
					itemLabelValue = itemValueValue;
				}
				if (itemLabelValue != null) {
					si.setLabel(itemLabelValue.toString());
				}
				list.add(si);
			}
		}
		return list;
	}
	
	public Object saveState(FacesContext context) {
		Object[] values = new Object[4];
		values[0] = super.saveState(context);
		values[1] = itemValue_;
		values[2] = itemLabel_;
		values[3] = nullLabel_;
		return values;
	}

	public void restoreState(FacesContext context, Object state) {
		Object values[] = (Object[]) state;
		super.restoreState(context, values[0]);
		itemValue_ = (String) values[1];
		itemLabel_ = (String) values[2];
		nullLabel_ = (String) values[3];
	}
}