package net.waltzstudio.montecarlo.filter;

import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.waltzstudio.montecarlo.object.Global;
import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.SingletonS2ContainerFactory;
import org.seasar.framework.util.StringUtil;
import org.seasar.struts.config.S2ExecuteConfig;
import org.seasar.struts.filter.RoutingFilter;
import org.seasar.struts.util.RequestUtil;
import org.seasar.struts.util.RoutingUtil;
import org.seasar.struts.util.S2ExecuteConfigUtil;

/**
 * プロジェクト識別子を認識するためのRoutingFilter
 */
public class ProjectRoutingFilter extends RoutingFilter {

	/**
	 * プロジェクト識別子チェック
	 */
	protected String[] checkProjectCode(String[] names, HttpServletRequest req) {
		if ("post".equals(req.getMethod().toLowerCase())) {
			return names;
		}
		if (names.length > 0 && !StringUtil.isEmpty(names[0])) {
			for (String path : Global.PROJECT_ROUTING_IGNORE_PATH) {
				if (path.equals(names[0])) {
					return names;
				}
			}
			req.setAttribute(Global.RequestInfo.PROJECT_CODE, names[0]);
			String[] names2 = new String[names.length - 1];
			for (int i = 0; i < names2.length; i++) {
				names2[i] = names[i + 1];
			}
			return names2;
		}
		return names;
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse res = (HttpServletResponse) response;
		String contextPath = req.getContextPath();
		if (contextPath.equals("/")) {
			contextPath = "";
		}
		String path = RequestUtil.getPath(req);
		if (!processDirectAccess(request, response, chain, path)) {
			return;
		}
		if (path.indexOf('.') < 0) {
			String[] names = StringUtil.split(path, "/");
			// プロジェクト識別子チェック
			names = checkProjectCode(names, req);
			S2Container container = SingletonS2ContainerFactory.getContainer();
			StringBuilder sb = new StringBuilder(50);
			for (int i = 0; i < names.length; i++) {
				if (container.hasComponentDef(sb + names[i] + "Action")) {
					String actionPath = RoutingUtil.getActionPath(names, i);
					String paramPath = RoutingUtil.getParamPath(names, i + 1);
					if (StringUtil.isEmpty(paramPath)) {
						if (!path.endsWith("/")) {
							String queryString = "";
							if (req.getQueryString() != null) {
								queryString = "?" + req.getQueryString();
							}
							res.sendRedirect(contextPath + path + "/" + queryString);
							return;
						} else if (S2ExecuteConfigUtil.findExecuteConfig(actionPath, req) != null) {
							forward((HttpServletRequest) request, (HttpServletResponse) response, actionPath, null, null);
							return;
						}
					} else {
						S2ExecuteConfig executeConfig = S2ExecuteConfigUtil.findExecuteConfig(actionPath, paramPath);
						if (executeConfig != null) {
							forward((HttpServletRequest) request, (HttpServletResponse) response, actionPath, paramPath, executeConfig);
							return;
						}
					}
				}
				if (container.hasComponentDef(sb + "indexAction")) {
					String actionPath = RoutingUtil.getActionPath(names, i - 1) + "/index";
					String paramPath = RoutingUtil.getParamPath(names, i);
					if (StringUtil.isEmpty(paramPath)) {
						if (!path.endsWith("/")) {
							String queryString = "";
							if (req.getQueryString() != null) {
								queryString = "?" + req.getQueryString();
							}
							res.sendRedirect(contextPath + path + "/" + queryString);
							return;
						} else if (S2ExecuteConfigUtil.findExecuteConfig(actionPath, req) != null) {
							forward((HttpServletRequest) request, (HttpServletResponse) response, actionPath, null, null);
							return;
						}
					} else {
						S2ExecuteConfig executeConfig = S2ExecuteConfigUtil.findExecuteConfig(actionPath, paramPath);
						if (executeConfig != null) {
							forward((HttpServletRequest) request, (HttpServletResponse) response, actionPath, paramPath, executeConfig);
							return;
						}
					}
				}
				sb.append(names[i] + "_");
			}
			if (container.hasComponentDef(sb + "indexAction")) {
				String actionPath = RoutingUtil.getActionPath(names, names.length - 1) + "/index";
				if (!path.endsWith("/")) {
					String queryString = "";
					if (req.getQueryString() != null) {
						queryString = "?" + req.getQueryString();
					}
					res.sendRedirect(contextPath + path + "/" + queryString);
					return;
				} else if (S2ExecuteConfigUtil.findExecuteConfig(actionPath, req) != null) {
					forward((HttpServletRequest) request, (HttpServletResponse) response, actionPath, null, null);
					return;
				}
			}
		}
		chain.doFilter(request, response);
	}

}
