/*
 * 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;

import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import nuts.core.lang.StringUtils;
import nuts.core.servlet.HttpServletUtils;
import nuts.core.servlet.URLHelper;
import nuts.exts.exception.UnknownHandlerException;
import nuts.exts.struts2.util.StrutsContextUtils;
import nuts.exts.xwork2.util.LocalizedTextUtils;

import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.Result;
import com.opensymphony.xwork2.UnknownHandler;
import com.opensymphony.xwork2.XWorkException;
import com.opensymphony.xwork2.XWorkMessages;
import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import com.opensymphony.xwork2.inject.Inject;

/**
 */
public class ServletUnknownHandler implements UnknownHandler {

//	private static Log log = LogFactory.getLog(FreemarkerServlet.class);
//
//	private static String FREEMARKER = "freemarker";
//	private static String VELOCITY = "velocity";
//	
//	private static Map<String, String> results;
//	static {
//		results = new HashMap<String, String>();
//		results.put("vm", VELOCITY);
//		results.put("vhtml", VELOCITY);
//		results.put("ftl", FREEMARKER);
//		results.put("fhtml", FREEMARKER);
//	}
//
	private Configuration configuration;
//	private ServletContext servletContext;

    private boolean welcomeToSlash = true;
    private boolean welcomeIgnoreDot = true;
	private String welcomeAction = "index";
//	private String defaultPackage = "nuts-default";
//	private String defaultAction = ActionSupport.class.getName();

    /**
     * Constructs the unknown handler.
     *
     * @param   configuration The XWork configuration.
     */
    @Inject
    public ServletUnknownHandler(Configuration configuration) {
        this.configuration = configuration;
    }

//    /**
//     * Constructs the unknown handler.
//     *
//     * @param   configuration The XWork configuration.
//     * @param   servletContext The servlet context used to help build the action configurations.
//     */
//    @Inject
//    public ServletUnknownHandler(Configuration configuration, ServletContext servletContext) {
//        this.configuration = configuration;
//        this.servletContext = servletContext;
//    }
//
//    /**
//	 * @param defaultPackage the defaultPackage to set
//	 */
//	@Inject(value=NutsStrutsConstants.NUTS_PACKAGE_DEFAULT, required=false)
//	public void setDefaultPackage(String defaultPackage) {
//		this.defaultPackage = defaultPackage;
//	}
//
//	/**
//	 * @param defaultAction the defaultAction to set
//	 */
//	@Inject(value=NutsStrutsConstants.NUTS_ACTION_SUPPORT, required=false)
//	public void setDefaultAction(String defaultAction) {
//		this.defaultAction = defaultAction;
//	}

	/**
	 * @param welcomeToSlash the welcomeToSlash to set
	 */
    @Inject(value=NutsStrutsConstants.NUTS_WELCOME_TO_SLASH, required=false)
	public void setWelcomeToSlash(String welcomeToSlash) {
		this.welcomeToSlash = Boolean.parseBoolean(welcomeToSlash);
	}

	/**
	 * @param welcomeIgnoreDot the welcomeIgnoreDot to set
	 */
    @Inject(value=NutsStrutsConstants.NUTS_WELCOME_IGNORE_DOT, required=false)
	public void setWelcomeIgnoreDot(String welcomeIgnoreDot) {
		this.welcomeIgnoreDot = Boolean.parseBoolean(welcomeIgnoreDot);
	}

	/**
	 * @param welcomeAction the welcomeAction to set
	 */
    @Inject(value=NutsStrutsConstants.NUTS_ACTION_WELCOME, required=false)
	public void setWelcomeAction(String welcomeAction) {
		this.welcomeAction = welcomeAction;
	}

	public static class RedirectAction {
		/**
		 * @return NONE
		 * @throws Exception if an error occurs
		 */
		public String execute() throws Exception {
			HttpServletRequest req = StrutsContextUtils.getServletRequest();
			HttpServletResponse res = StrutsContextUtils.getServletResponse();

			String uri = HttpServletUtils.getRequestURI(req);
			String url = URLHelper.buildURL(uri + "/", req.getParameterMap());
    		HttpServletUtils.sendRedirect(res, url);
			
    		return Action.NONE;
    	}
	}

	public ActionConfig handleUnknownAction(String namespace, String actionName) throws XWorkException {
		if (welcomeToSlash) {
			boolean doFind = true;
			
			HttpServletRequest request = StrutsContextUtils.getServletRequest();
			if (welcomeIgnoreDot) {
				String uri = HttpServletUtils.getRequestURI(request);
				String acn = StringUtils.substringAfterLast(uri, "/");
				doFind = !acn.contains(".");
			}
//					
//			        ResultTypeConfig resultTypeConfig = getResultTypeConfig(uri);
//					try {
//						File f = new File(servletContext.getRealPath(uri));
//						if (f.isFile() && f.exists()) {
//							return buildActionConfig(uri, resultTypeConfig);
//						}
//					}
//					catch (Exception e) {
//						log.warn(e.getMessage(), e);
//					}
			//
//					if (FREEMARKER.equals(resultTypeConfig.getName()) 
//							|| VELOCITY.equals(resultTypeConfig.getName())) {
//						return buildActionConfig(uri, resultTypeConfig);
//					}

			if (doFind) {
				if (StringUtils.isEmpty(namespace)) {
					namespace = "/";
				}
	
				String nn = namespace;
				if (StringUtils.isNotEmpty(actionName)) {
					if (!"/".equals(namespace)) {
						nn += '/';
					}
					nn += actionName;
				}
	
				ActionConfig actionConfig = configuration.getRuntimeConfiguration().getActionConfig(nn, "");
		        if (actionConfig == null) {
			        if (StringUtils.isNotEmpty(welcomeAction)) {
				        actionConfig = configuration.getRuntimeConfiguration().getActionConfig(nn, welcomeAction);
			        }
		        }
	
		        if (actionConfig != null) {
		        	if (StringUtils.isNotEmpty(actionName)) {
		        		actionConfig = new ActionConfig.Builder("/", "redirect", 
		        			RedirectAction.class.getName()).build();
		        	}
		        	return actionConfig;
		        }
			}
		}

		String message;
		if ((namespace != null) && (namespace.trim().length() > 0)) {
			message = LocalizedTextUtils.findDefaultText(
				XWorkMessages.MISSING_PACKAGE_ACTION_EXCEPTION, Locale.getDefault(), new String[] {
						namespace, actionName });
		}
		else {
			message = LocalizedTextUtils.findDefaultText(XWorkMessages.MISSING_ACTION_EXCEPTION,
				Locale.getDefault(), new String[] { actionName });
		}
		throw new UnknownHandlerException(message);
	}

	public Result handleUnknownResult(ActionContext actionContext, String actionName,
			ActionConfig actionConfig, String resultCode) throws XWorkException {
		return null;
	}

	public Object handleUnknownActionMethod(Object action, String methodName)
			throws NoSuchMethodException {
		return null;
	}

//	protected ResultTypeConfig getResultTypeConfig(String path) {
//		PackageConfig pkg = configuration.getPackageConfig(defaultPackage);
//        if (pkg == null) {
//            throw new ConfigurationException("Unknown default package [" + defaultPackage + "]");
//        }
//
//        String ext = IOUtils.getFileNameExtension(path);
//		String result = results.get(ext);
//		if (result == null) {
//			result = "dispatcher";
//		}
//		return pkg.getAllResultTypeConfigs().get(result);
//	}
//
//	protected ActionConfig buildActionConfig(String path, ResultTypeConfig resultTypeConfig) {
//		Map<String, ResultConfig> results = new HashMap<String, ResultConfig>();
//		HashMap<String, String> params = new HashMap<String, String>();
//		if (resultTypeConfig.getParams() != null) {
//			params.putAll(resultTypeConfig.getParams());
//		}
//		params.put(resultTypeConfig.getDefaultResultParam(), path);
//
//		ResultConfig config = new ResultConfig.Builder(Action.SUCCESS,
//			resultTypeConfig.getClassName()).addParams(params).build();
//		results.put(Action.SUCCESS, config);
//
//		// addInterceptors(interceptors).
//		return new ActionConfig.Builder(defaultPackage, 
//			"execute", defaultAction).addResultConfigs(results).build();
//	}
}
