package org.seasar.jsf.application;

import java.io.IOException;
import java.util.Iterator;
import java.util.Locale;

import javax.faces.application.Application;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.render.RenderKitFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.SingletonS2ContainerFactory;
import org.seasar.framework.util.StringUtil;
import org.seasar.jsf.ViewRenderer;
import org.seasar.jsf.util.ExternalContextUtil;

public class S2ViewHandler extends ViewHandler {

	private ViewHandler originalViewHandler;

	private ViewRenderer viewRenderer;

	public S2ViewHandler(ViewHandler originalViewHandler) {
		this.originalViewHandler = originalViewHandler;
	}

	public Locale calculateLocale(FacesContext context) {
		Application app = context.getApplication();
		Iterator locales = context.getExternalContext().getRequestLocales();
		while (locales.hasNext()) {
			Locale locale = (Locale) locales.next();
			Iterator supportedLocales = app.getSupportedLocales();
			while (supportedLocales.hasNext()) {
				Locale supportedLocale = (Locale) supportedLocales.next();
				if (locale.equals(supportedLocale)) {
					return supportedLocale;
				}
				String country = supportedLocale.getCountry();
				if (locale.getLanguage().equals(supportedLocale.getLanguage())
						&& StringUtil.isEmpty(country)) {
					return supportedLocale;
				}
			}
		}
		Locale defaultLocale = app.getDefaultLocale();
		return defaultLocale != null ? defaultLocale : Locale.getDefault();
	}

	public String calculateRenderKitId(FacesContext context) {
		String renderKitId = context.getApplication().getDefaultRenderKitId();
		return renderKitId != null ? renderKitId
				: RenderKitFactory.HTML_BASIC_RENDER_KIT;
	}

	public String getActionURL(FacesContext context, String viewId) {
		return originalViewHandler.getActionURL(context, viewId);
	}

	public String getResourceURL(FacesContext context, String path) {
		return originalViewHandler.getResourceURL(context, path);
	}

	public UIViewRoot createView(FacesContext context, String viewId) {
		return originalViewHandler.createView(context, viewId);
	}

	public void renderView(FacesContext context, UIViewRoot viewRoot)
			throws IOException {

		ExternalContext externalContext = context.getExternalContext();
		String path = ExternalContextUtil.getViewId(externalContext);
		if (path.equals(viewRoot.getViewId())) {
			HttpServletRequest request = ExternalContextUtil.getRequest(externalContext);
			HttpServletResponse response = ExternalContextUtil
					.getResponse(externalContext);
			getViewRenderer().renderView(path, request, response);
		} else {
			externalContext.dispatch(viewRoot.getViewId());
		}
	}

	protected ViewRenderer getViewRenderer() {
		if (viewRenderer == null) {
			S2Container container = SingletonS2ContainerFactory.getContainer();
			viewRenderer = (ViewRenderer) container
					.getComponent(ViewRenderer.class);
		}
		return viewRenderer;
	}

	public UIViewRoot restoreView(FacesContext context, String viewId) {
		return originalViewHandler.restoreView(context, viewId);
	}

	public void writeState(FacesContext context) throws IOException {
		originalViewHandler.writeState(context);
	}
}