package com.cloudcross.ssp.base.web;

import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.ServletContext;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ApplicationObjectSupport;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.context.WebApplicationContext;

import com.cloudcross.ssp.model.Account;
import com.cloudcross.ssp.service.IAccountService;
import com.cloudcross.ssp.common.utils.Assert;
import com.cloudcross.ssp.common.utils.DateUtil.DateFmts;
/**
 * 简单控制器。
 * 
 * @author qaohao
 */
public abstract class SimpleController extends ApplicationObjectSupport
		implements InitializingBean {
	private static final String SUBCLAZZ_SUFFIX = "Controller";

	private static final Logger LOG = Logger.getLogger(SimpleController.class);
	
	protected static final String WEB_LOCATOR = "com.cloudcross.ssp.web";

	public static final String OK = "ok";
	public static final String ERROR = "error";
	
	/**
	 * 功能首页模板路径
	 */
	protected String index;
	
	/**
	 * @return 返回到<code>page</code>页。
	 */
	public final String page(String page) {
		return index.concat("/").concat(page);
	}
	
	/**
	 * 重定向到某个uri。
	 * 
	 * @param uri
	 * @return
	 */
	public final String redirect(String uri) {
		return "redirect:" + uri;
	}
	
	/**
	 * 请求转发到某个uri上。
	 * 
	 * @param uri
	 * @return
	 */
	public final String forward(String uri) {
		return "forward:" + uri;
	}
	
	/**
	 * 从spring上下文中找<code>beanId</code>对象。
	 * 
	 * @param beanClazz
	 *            实例类型
	 * @param beanId
	 *            实例spring中ID
	 * @return 实例对象
	 */
	public final <T> T getBean(Class<T> beanClazz, String beanId) {
		Assert.notNull(beanClazz, "beanClazz can't be null.");
		Assert.isTrue(StringUtils.isNotBlank(beanId), "beanId can't be empty.");
		return beanClazz.cast(getApplicationContext().getBean(beanId));
	}

	/**
	 * 从spring上下文中找<code>beanClazz</code>类型的对象。
	 * 
	 * @param beanClazz
	 *            实例类型
	 * @return 实例对象
	 */
	public final <T> T getBean(Class<T> beanClazz) {
		Assert.notNull(beanClazz, "beanClazz can't be null.");
		return getApplicationContext().getBean(beanClazz);
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void afterPropertiesSet() throws Exception {
		Class<?> myClazz = this.getClass();
		String fileName = myClazz.getSimpleName();
		if (fileName.endsWith(SUBCLAZZ_SUFFIX)) {
			fileName = fileName.substring(0,
					fileName.length() - SUBCLAZZ_SUFFIX.length());
		}
		
		// camel case to mid-line one.
		fileName = fileName.replaceAll(
				String.format("%s|%s|%s",
						"(?<=[A-Z])(?=[A-Z][a-z])",
						"(?<=[^A-Z])(?=[A-Z])",
						"(?<=[A-Za-z])(?=[^A-Za-z])"), "-").toLowerCase();
		
		String relativeLocator = myClazz.getPackage().getName().trim()
				.replaceFirst(WEB_LOCATOR, StringUtils.EMPTY)
				.replaceAll("\\.", "/");
		
		index = StringUtils.isBlank(relativeLocator) ? fileName
				: relativeLocator.concat("/").concat(fileName);
		LOG.debug("Controller: " + myClazz + " index page url is :" + index);
	}
	
	/**
	 * @return 当前登录用户
	 * @see User
	 */
	public Account getLoginUser() {
		if (StringUtils.isBlank(getLoginUsername())) {
			return null;
		}
		IAccountService userService = getBean(IAccountService.class);
		Account loginUser = userService.querySingleAccount(getLoginUsername());
		return loginUser;
	}

	/**
	 * @return 当前登录用户名
	 */
	public String getLoginUsername() {
		Object principal = SecurityContextHolder.getContext()
				.getAuthentication().getPrincipal();
		if (principal instanceof UserDetails) {
			return ((UserDetails) principal).getUsername();
		} else {
			return principal.toString();
		}
	}
	
	public ServletContext getServletContext() {
		ApplicationContext ac = getApplicationContext();
		if (ac instanceof WebApplicationContext) {
			return ((WebApplicationContext) ac).getServletContext();
		}
		return null;
	}
	
	@InitBinder
	protected void initBinder(WebDataBinder binder) {
		LOG.debug("to customize request parameter binding with PropertyEditors");
		binder.registerCustomEditor(Date.class, new CustomDateEditor(
				new SimpleDateFormat(DateFmts.YYYY_MM_DD), true));
	}
}
