/*
 * This file is part of Nuts Framework.
 * Copyright(C) 2009-2012 Nuts Develop Team.
 *
 * Nuts Framework is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License any later version.
 *
 * Nuts Framework is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Nuts Framework. If not, see <http://www.gnu.org/licenses/>.
 */
package nuts.exts.struts2.views.java.simple;

import nuts.exts.struts2.views.java.AbstractTemplateRenderer;
import nuts.exts.struts2.views.java.Attributes;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.struts2.components.ListUIBean;
import org.apache.struts2.components.OptGroup;
import org.apache.struts2.components.template.TemplateRenderingContext;
import org.apache.struts2.util.ContainUtil;
import org.apache.struts2.util.MakeIterator;


public class NutsSelectRenderer extends AbstractTemplateRenderer {
	public NutsSelectRenderer(TemplateRenderingContext context) {
		super(context);
	}

	@SuppressWarnings("unchecked")
	public void render() throws IOException {
        Attributes a = new Attributes();

        Object value = params.get("nameValue");

        a.id(params)
         .name(params)
		 .css(this, "n-select")
         .size(params)
         .disabled(params)
         .readonly(params)
         .multiple(params)
         .tabindex(params)
         .title(params)
         .commons(params)
         .events(params)
         .dynamics(params);
        
		stag("select", a);

		// options

		// header
		String headerKey = (String)params.get("headerKey");
		String headerValue = (String)params.get("headerValue");
		if (headerKey != null && headerValue != null) {
			boolean selected = ContainUtil.contains(value,
					params.get("headerKey"));
			writeOption(headerKey, headerValue, selected);
		}

		// emptyoption
		Object emptyOption = params.get("emptyOption");
		if (emptyOption != null
				&& emptyOption.toString().equals(Boolean.toString(true))) {
			boolean selected = ContainUtil.contains(value, "")
					|| ContainUtil.contains(value, null);
			writeOption("", "", selected);
		}

		Object listObj = params.get("list");
		String listKey = (String)params.get("listKey");
		String listValue = (String)params.get("listValue");
		if (listObj != null) {
			Iterator itt = MakeIterator.convert(listObj);
			while (itt.hasNext()) {
				Object item = itt.next();
				stack.push(item);

				// key
				Object itemKey = findValue(listKey != null ? listKey : "top");
				// value
				Object itemValue = findValue(listValue != null ? listValue : "top");

				boolean selected = ContainUtil.contains(value, itemKey);

				writeOption(itemKey, itemValue, selected);

				stack.pop();
			}
		}

		// opt group
		List<ListUIBean> listUIBeans = (List<ListUIBean>)params.get(OptGroup.INTERNAL_LIST_UI_BEAN_LIST_PARAMETER_KEY);
		if (listUIBeans != null) {
			for (ListUIBean listUIBean : listUIBeans) {
				writeOptionGroup(listUIBean, value);
			}
		}

		etag("select");
		writeMultiHidden();
	}

	protected void writeMultiHidden() throws IOException {
        if (Attributes.isTrue(params.get("multiple")) &&
        		!Boolean.FALSE.equals(params.get("multiselectIntercept"))) {
	        //hidden input
	        Attributes attrs = new Attributes();
	        attrs.add("type", "hidden")
	                .add("id", "__multiselect_" + params.get("id"))
	                .add("name", "__multiselect_" + params.get("name"))
	                .add("value", "")
	                .addIfTrue("disabled", params.get("disabled"));
	        xtag("input", attrs);
        }
	}

	protected void writeOption(Object value, Object text, boolean selected)
			throws IOException {
		Attributes attrs = new Attributes();
		attrs.addIfExists("value", value).addIfTrue("selected", selected);

		stag("option", attrs);
		body(text == null ? null : text.toString());
		etag("option");
	}

	protected void writeOptionGroup(ListUIBean listUIBean, Object value)
			throws IOException {
		Map params = listUIBean.getParameters();
		Attributes attrs = new Attributes();
		attrs.addIfExists("label", params.get("label"))
			.addIfTrue("disabled", params.get("disabled"));
		stag("optgroup", attrs);

		// options
		Object listObj = params.get("list");
		if (listObj != null) {
			Iterator itt = MakeIterator.convert(listObj);
			String listKey = (String)params.get("listKey");
			String listValue = (String)params.get("listValue");
			while (itt.hasNext()) {
				Object optGroupBean = itt.next();
				stack.push(optGroupBean);

				Object tmpKey = stack.findValue(listKey != null ? listKey : "top");
				Object tmpValue = stack.findValue(listValue != null ? listValue : "top");
				boolean selected = ContainUtil.contains(value, tmpKey);
				writeOption(tmpKey, tmpValue, selected);

				stack.pop();
			}
		}

		etag("optgroup");
	}
}
