package cn.myapps.runtime.rest.common.controller;

import java.util.Collection;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.Option;
import com.jayway.jsonpath.PathNotFoundException;

import cn.myapps.authtime.common.service.AuthTimeServiceManager;
import cn.myapps.authtime.department.model.DepartmentVO;
import cn.myapps.authtime.user.model.UserVO;
import cn.myapps.authtime.user.service.UserProcess;
import cn.myapps.base.web.WebUser;
import cn.myapps.common.controller.ErrorMessage;
import cn.myapps.common.controller.Resource;
import cn.myapps.common.controller.ResourceNotFoundException;
import cn.myapps.common.data.ParamsTable;
import cn.myapps.common.exception.OBPMValidateException;
import cn.myapps.common.util.SequenceGenerator;
import cn.myapps.common.util.StringUtil;
import cn.myapps.constans.Web;
import cn.myapps.runtime.common.service.RunTimeServiceManager;
import cn.myapps.runtime.dynaform.document.ejb.DocumentProcess;
import cn.myapps.runtime.dynaform.document.ejb.Item;
import cn.myapps.runtime.dynaform.document.model.PureDocument;
import cn.myapps.runtime.rest.department.model.Department;
import cn.myapps.runtime.rest.user.model.User;
import cn.myapps.runtime.workflow.WorkflowException;

/**
 * REST服务模块的抽象控制器接口，提供了通用的数据结构和异常处理机制。
 * @author Happy
 *
 */
@RestController
public abstract class AbstractRESTController {
	
	protected static Configuration configuration = Configuration.defaultConfiguration();
	static{
		configuration = configuration.addOptions(Option.DEFAULT_PATH_LEAF_TO_NULL);
	}
	
	
	@Autowired  
	protected HttpServletRequest request;
	
	private ParamsTable params;
	
	/**
	 * 从Http请求包体中解析User对象实例
	 * 
	 * @param postBody 请求包体内容（JSON）
	 * 
	 * @return {@link User}
	 */
	public User parseUser(String postBody){
		if(StringUtils.isBlank(postBody)) {
			throw new java.lang.IllegalArgumentException("请求包体内容为空或格式不合法");
		}
		DocumentContext parse = JsonPath.parse(postBody, configuration);
		String userName = parse.read("$.username");
		String account = parse.read("$.account");
		String gender = parse.read("$.gender");
		String mobileNumber = parse.read("$.mobilenumber");
		String email = parse.read("$.email");
		String certificateTypeId = parse.read("$.certificatetypeid");
		String certificateNumber = parse.read("$.certificatenumber");
		String departmentId = parse.read("$.departmentid");
		String order = parse.read("$.order");
		String isTop = parse.read("$.istop");
		String isLeader = parse.read("$.isleader");
		String entryDate = parse.read("$.entrydate");
		LinkedHashMap<?, ?> extend = parse.read("$.extend");
		String extendStr = extend.toString();
		User user = new User();
		user.setUserName(userName);
		user.setAccount(account);
		user.setGender(gender);
		user.setMobileNumber(mobileNumber);
		user.setEmail(email);
		user.setCertificateTypeId(certificateTypeId);
		user.setCertificateNumber(certificateNumber);
		user.setDepartmentId(departmentId);
		user.setOrder(order);
		user.setIsTop(isTop);
		user.setIsLeader(isLeader);
		user.setEntryDate(entryDate);
		user.setExtend(extendStr);
		return user;
	}
	
	/**
	 * 从Http请求包体中解析Department对象实例
	 * 
	 * @param postBody 请求包体内容（JSON）
	 * 
	 * @return {@link Department}
	 * @throws Exception 
	 */
	public Department parseDepartment(String postBody) throws Exception{
		if(StringUtils.isBlank(postBody)) {
			throw new java.lang.IllegalArgumentException("请求包体内容为空或格式不合法");
		}
		DocumentContext parse = JsonPath.parse(postBody, configuration);
		String name = parse.read("$.name");
		String parentId = parse.read("$.parentid");
		String order = parse.read("$.order");
		String description = parse.read("$.description");
		String isVirtual = parse.read("$.isvirtual");
		String master = parse.read("$.master");
		String leader = parse.read("$.leader");
		String extend = parse.read("$.extend");
		Department dept = new Department();
		dept.setID(SequenceGenerator.getSequence());
		dept.setName(name);
		dept.setParentId(parentId);
		dept.setOrder(order);
		dept.setDescription(description);
		dept.setIsVirtual(isVirtual);
		dept.setMaster(master);
		dept.setLeader(leader);
		dept.setExtend(extend);
		return dept;
	}
	
	/**
	 * 从Http请求包体中解析Document对象实例
	 * 
	 * @param postBody 请求包体内容（JSON）
	 * 
	 * @param applicationId 应用id
	 * 
	 * @return {@link PureDocument}
	 */
	public PureDocument parseDocument(String postBody,String applicationId,WebUser user) throws Exception{
		
		if(StringUtils.isBlank(postBody)) throw new java.lang.IllegalArgumentException("请求包体内容为空或格式不合法");
		DocumentContext parse = JsonPath.parse(postBody, configuration);
		String id = parse.read("$.id");
		if(StringUtils.isBlank(id)) throw new java.lang.IllegalArgumentException("请求包体id属性不能为空");
		DocumentProcess docProcess = RunTimeServiceManager.documentProcess( applicationId);
		PureDocument doc = (PureDocument) docProcess.doView(id);;
		if(doc == null){
			doc = new PureDocument();
			doc.setId(id);
			doc.setAuthor(user);
			
			DepartmentVO defaultDept = (DepartmentVO)AuthTimeServiceManager.departmentRuntimeService().doView(user.getDefaultDepartment());
			
			if (!StringUtil.isBlank(user.getDefaultDepartment())) {
				doc.setAuthorDeptIndex(defaultDept.getIndexCode());
			}
			doc.setDomainid(user.getDomainid());
			doc.setCreated(new Date());
			doc.setIstmp(true);
			doc.setLastmodifier(user.getId());
			doc.setApplicationid(applicationId);
		}
		String summary = parse.read("$.summary");
		if(!StringUtils.isBlank(summary)){
			doc.setSummary(summary);
		}
		Map<String, Object> items = parse.read("$.items");
		if (items != null) {
			for (Map.Entry<String, Object> entry : items.entrySet()) {
				String key = entry.getKey();
				Object value = entry.getValue();
				Item item = new Item();
				item.setName(key);
				item.setValue(value);
				doc.addItem(item);
			}
		}
		
		return doc;
		
	}
	
	public WebUser getUser(){
		WebUser webUser = null;
		String userId = request.getParameter("userCode");
		if(!StringUtils.isBlank(userId)){
			try {
				UserProcess up = AuthTimeServiceManager.userRuntimeService();
				UserVO userVO = (UserVO) up.login(userId);
				if(userVO != null){
					webUser = new WebUser(userVO);
					WebUser.setWebUser(webUser, request);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		return webUser;
	}
	
	public ParamsTable getParams() {
		if (params == null) {
			params = ParamsTable.convertHTTP(request);

			if (params.getParameter("_pagelines") == null){
				params.setParameter("_pagelines", Web.DEFAULT_LINES_PER_PAGE);
			}
		}

		return params;
	}
	public ParamsTable getParams(HttpServletRequest request) {
		if (params == null) {
			params = ParamsTable.convertHTTP(request);
			String sessionId = request.getSession().getId();
			params.setSessionid(sessionId);

			if (params.getParameter("_pagelines") == null){
				params.setParameter("_pagelines", Web.DEFAULT_LINES_PER_PAGE);
			}
		}

		return params;
	}
	
	protected Resource success(String errmsg, Object data) {
		return new Resource(0, errmsg, data, null);
	}
	
	protected Resource error(int errcode, String errmsg, Collection<ErrorMessage> errors) {
		return new Resource(errcode, errmsg, null, errors);
	}

    private Resource resourceValue;

    public Resource getResourceValue() {
        return resourceValue;
    }

    public void setResourceValue(Resource resourceValue) {
        this.resourceValue = resourceValue;
    }

    /**
     * 资源未找到的异常，返回404的状态，且返回错误信息。
     * @param e
     * @return
     */
    @ExceptionHandler(ResourceNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public Resource resourceNotFound(ResourceNotFoundException e) {
        return error(404, "Not Found", null);
    }

    /**
     * 运行时异常，服务器错误，返回500状态，返回服务器错误信息。
     * @param e
     * @return
     */
    @ExceptionHandler(RuntimeException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Resource error(RuntimeException e) {
    	e.printStackTrace();
        return error(500, "Server Error:"+e.getMessage(), null);
    }
    
    /**
     * 资源未找到的异常，返回404的状态，且返回错误信息。
     * @param e
     * @return
     */
    @ExceptionHandler(OBPMValidateException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Resource serverError(OBPMValidateException e) {
    	e.printStackTrace();
        return error(500, "Server Error:"+e.getMessage(), null);
    }

    /**
     * 传参错误。
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    @ResponseStatus(HttpStatus.NOT_ACCEPTABLE)
    public Resource resourceNotFound(MethodArgumentTypeMismatchException e) {
        return error(40035, "不合法的参数", null);
    }
    
    /**
     * 请求包体解析错误。
     * @param e
     * @return
     */
    @ExceptionHandler(PathNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_ACCEPTABLE)
    public Resource requestbodyError(PathNotFoundException e) {
    	e.printStackTrace();
    	return error(406, "请求包体参数出错", null);
    }
    
    /**
     * 传参错误。
     * @param e
     * @return
     */
    @ExceptionHandler(WorkflowException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Resource WorkflowException(WorkflowException e) {
        return error(50001, e.getMessage(), null);
    }
    
    

}
