package com.blueland.ebpm.bean;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.activiti.engine.impl.persistence.entity.HistoricProcessInstanceEntity;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.blueland.bpm.application.model.ApplicationEntity;
import com.blueland.bpm.application.service.ApplicationManager;
import com.blueland.bpm.common.page.Page;
import com.blueland.bpm.engine.config.model.ActivityInfoConfig;
import com.blueland.bpm.engine.config.model.ActivityOperatePower;
import com.blueland.bpm.engine.config.model.DataObject;
import com.blueland.bpm.engine.config.model.DataObjectRelation;
import com.blueland.bpm.engine.config.model.ProcessInfoConfig;
import com.blueland.bpm.engine.config.model.SysGlType;
import com.blueland.bpm.engine.core.model.ActivityDefinitionModel;
import com.blueland.bpm.engine.core.model.ActivityInstanceModel;
import com.blueland.bpm.engine.core.model.ProcessDefinitionModel;
import com.blueland.bpm.engine.core.model.ProcessInputModel;
import com.blueland.bpm.engine.core.model.ProcessInstanceModel;
import com.blueland.bpm.engine.core.model.ProcessLogModel;
import com.blueland.bpm.idea.model.CommonIdeaEntity;

/**
 * 转换引擎内部的数据结构为对外提供的格式，严格跟接口文档一致
 * @author janus
 *
 */
@Service
public class BeansBuilder {	
	@Autowired
	private ApplicationManager applicationManager;
	
	private static Map<String, ApplicationEntity> applications = new HashMap<String, ApplicationEntity>();
	
	public String getApplicationUrl(String app_id) {
		ApplicationEntity app = applications.get(app_id);
		if(app != null)
			return app.getAppAccessUrl();
		
		app = applicationManager.getById(app_id);
		if(app!=null) {
			applications.put(app_id, app);
			return app.getAppAccessUrl();
		}
		
		return "";		
	}
	
	public ProcessDefinitionBean build(ProcessDefinitionModel model) {
		ProcessDefinitionBean bean = new ProcessDefinitionBean();
		BeanUtils.copyProperties(model, bean);
		ProcessInfoConfig config = model.getProcessInfoConfig();
		bean.setDescription(config.getRemark());
		bean.setCreateTime(config.getCreateTime());
		bean.setLastUpdateTime(config.getLastUpdateTime());
		bean.setPageUrl(config.getProcessPageUrl());
		//bean.setMportalProtocol(config.getMprotocol());
		bean.setMportalUrl(config.getMurl());
		bean.setOtherSysDealStatus(config.getOtherSysDealStatus());
		//bean.setCportalProtocol(config.getCprotocol());
		bean.setHandlerClassPath(config.getProcessHandlerClassPath());
		bean.setTypeId(config.getProcessTypeId());
		bean.setTypeName(config.getProcessTypeName());
		bean.setOrder(config.getProcessStartOrder());
		bean.setShow(config.getProcessStartIsshow().equals("Y"));
		bean.setRelease(config.getProcessMgrState().equals("RELEASE"));
		bean.setArisCode(config.getArisCode());
		return bean;
	}
	
	public ActivityDefinitionBean build(ActivityDefinitionModel model) {
		ActivityDefinitionBean bean = new ActivityDefinitionBean();
		BeanUtils.copyProperties(model, bean);
		bean.setActDefType(model.getActType());
		ActivityInfoConfig config = model.getActivityInfoConfig();
		bean.setActDefDealType(config.getActivityDefDealType());
		bean.setActDefChildType(config.getActivityDefChildType());
		bean.setPageUrl(config.getActivityPageInfo());
		//bean.setMportalProtocol(config.getMprotocol());
		bean.setMportalUrl(config.getMurl());
		bean.setOtherSysDealStatus(config.getOtherSysDealStatus());
		//bean.setCportalProtocol(config.getCprotocol());
		bean.setJumpType(config.getJumpType());
		bean.setIdeaDisplayArea(config.getIdeaDisplayArea());
		bean.setShowIdea(config.getIsShowIdea());
		bean.setActLimitTime(config.getActivityLimitTime());
		bean.setDescription(config.getRemark());
		bean.setActDefOrder(config.getActivityOrder());
		return bean;
	}
	
	public List<ActivityDefinitionBean> buildActDefList(List<ActivityDefinitionModel> list){
		List<ActivityDefinitionBean> result = new ArrayList<ActivityDefinitionBean>();
		for (int i=0; i<list.size(); i++) {
			ActivityDefinitionBean bean = build(list.get(i));
			result.add(bean);
		}
		return result;
	}
	
	public List<ProcessDefinitionBean> buildProcDefList(List<ProcessDefinitionModel> list){
		List<ProcessDefinitionBean> result = new ArrayList<ProcessDefinitionBean>();
		for (int i=0; i<list.size(); i++) {
			ProcessDefinitionBean bean = build(list.get(i));
			result.add(bean);
		}
		return result;
	}
	
	public List<ProcessInstanceBean> buildProcInstList(List<ProcessInstanceModel> list){
		List<ProcessInstanceBean> result = new ArrayList<ProcessInstanceBean>();
		for(int i=0;i<list.size();i++) {
			ProcessInstanceBean bean = build(list.get(i));
			result.add(bean);
		}
		return result;
	}
	
	public List<ProcessDefinitionBean> build(Map<String,List<ProcessDefinitionModel>> maps){
		List<ProcessDefinitionBean> result = new ArrayList<ProcessDefinitionBean>();
		for(Map.Entry<String, List<ProcessDefinitionModel>> entry : maps.entrySet()) {
			List<ProcessDefinitionBean> dest = buildProcDefList(entry.getValue());
			result.addAll(dest);
		}
		Collections.sort(result, new Comparator<ProcessDefinitionBean>(){
            public int compare(ProcessDefinitionBean arg0, ProcessDefinitionBean arg1) {
            	if(arg0.getOrder() == null)
            		return 1;
            	if(arg1.getOrder() == null)
            		return -1;
                return arg0.getOrder().compareTo(arg1.getOrder());
            }
        });
		return result;
	}
	
	public ActivityInstanceBean build(ActivityInstanceModel model) {
		ActivityInstanceBean bean = new ActivityInstanceBean();
		BeanUtils.copyProperties(model, bean);
		bean.setProcInstTitle(model.getProcTitle());
		bean.setActInstState(model.getActState());
		bean.setSendUserOrgId(model.getSenderOrgId());
		bean.setSendUserOrgName(model.getSenderOrgName());
		bean.setReceiverUserOrgId(model.getReceiverOrgId());
		bean.setReceiverUserOrgName(model.getReceiverOrgName());
//		String URL = this.getApplicationUrl(model.getTenantId());
//		if(URL.indexOf('?') != -1)
//			URL += "&procDefId=" + bean.getProcDefId();
//		else
//			URL += "?procDefId=" + bean.getProcDefId();
//		URL += "&procInstId=" + bean.getProcInstId() + "&actDefId=" + bean.getActDefId() + "&actInstId=" + bean.getActInstId();
		return bean;
	}
	
	public Page<ActivityInstanceBean> buildActInstPage(Page<ActivityInstanceModel> page){
		 Page<ActivityInstanceBean> result = new Page<ActivityInstanceBean>(page.getThisPageNumber(),page.getPageSize(),page.getTotalCount());
		 BeanUtils.copyProperties(page, result, "result");
		 List<ActivityInstanceBean> beans = new ArrayList<ActivityInstanceBean>();
		 for(int i=0;i<page.getResult().size();i++) {
			 beans.add(build(page.getResult().get(i)));
		 }
		 result.setResult(beans);
		 return result;
	}
	
	public List<ActivityInstanceBean> buildActInstList(List<ActivityInstanceModel> list){
		List<ActivityInstanceBean> result = new ArrayList<ActivityInstanceBean>();
		for(ActivityInstanceModel model : list) {
			result.add(this.build(model));
		}
		return result;
	}
	
	public ProcessInstanceBean build(ProcessInstanceModel model) {
		ProcessInstanceBean bean = new ProcessInstanceBean();
		BeanUtils.copyProperties(model, bean);
		bean.setProcInstTitle(model.getProcTitle());
//		if(model.getCurrentActivity() != null) {//结束流程为空
//			bean.setCurActDefId(model.getCurrentActivity().getActDefId());
//			bean.setCurActDefName(model.getCurrentActivity().getActDefName());
//		}
		bean.setStartUserOrgId(model.getStarterOrgId());
		bean.setStartUserOrgName(model.getStarterOrgName());
		bean.setProcInstState(model.getProcState());
		List<ActivityInstanceBean> actInstBeans=new ArrayList<ActivityInstanceBean>();
		if(model.getNextActivity()!=null&&!model.getNextActivity().isEmpty()){
			List<ActivityInstanceModel> actInsts=model.getNextActivity();
			for (ActivityInstanceModel actInst : actInsts) {
				actInstBeans.add(this.build(actInst));
			}
			bean.setNextActInsts(actInstBeans);
		}
		return bean;
	}
	
	public ProcessInstanceBean build(HistoricProcessInstanceEntity entity) {
		ProcessInstanceBean bean = new ProcessInstanceBean();
		bean.setProcDefId(entity.getProcessDefinitionId());
		bean.setProcDefName(entity.getProcessDefinitionName());
		bean.setProcInstTitle(entity.getProcTitle());
		bean.setBusinessKey(entity.getBusinessKey());
		bean.setCreateTime(entity.getStartTime());
		bean.setStartUserId(entity.getStartUserId());
		bean.setProcInstId(entity.getId());
		bean.setProcInstState(String.valueOf(entity.getProcState()));
		bean.setTenantId(entity.getTenantId());
		bean.setFinishTime(entity.getEndTime());
		bean.setTopProcInstId(entity.getTopProcessInstanceId());
		bean.setParentProcInstId(entity.getSuperProcessInstanceId());
		return bean;
	}
	
	public Page<ProcessInstanceBean> buildInstProcPage(Page<ProcessInstanceModel> page){
		 Page<ProcessInstanceBean> result = new Page<ProcessInstanceBean>(page.getThisPageNumber(),page.getPageSize(),page.getTotalCount());
		 BeanUtils.copyProperties(page, result, "result");
		 List<ProcessInstanceBean> beans = new ArrayList<ProcessInstanceBean>();
		 for(int i=0;i<page.getResult().size();i++) {
			 beans.add(build(page.getResult().get(i)));
		 }
		 result.setResult(beans);
		 return result;
	}
	
	public ExtAttributBean build(DataObject model) {
		ExtAttributBean bean = new ExtAttributBean();
		BeanUtils.copyProperties(model, bean);
		return bean;
	}
	
	public List<ExtAttributBean> build(List<DataObjectRelation> list){
		List<ExtAttributBean> result = new ArrayList<ExtAttributBean>();
		for(DataObjectRelation dor : list) {
			ExtAttributBean bean=build(dor.getDataObject());
			bean.setActDefId(dor.getActivityDefId());
			bean.setProcDefId(dor.getProcessDefId());
			result.add(build(dor.getDataObject()));
		}
		return result;
	}
	
	public ProcessLogBean build(ProcessLogModel model) {
		ProcessLogBean bean = new ProcessLogBean();
		if(model.getComment() != null) {
			bean.setCommentFullMessage(model.getComment().getMessage());
			bean.setCommentDisplayArea(model.getComment().getDisplayArea());
		}
		bean.setStartTime(model.getHistoricTaskInstance().getStartTime());
		bean.setEndTime(model.getHistoricTaskInstance().getEndTime());
		bean.setSendUserId(model.getSendUserId());
		bean.setSendUserName(model.getSendUserName());
		bean.setSendOrgId(model.getSendOrgId());
		bean.setSendOrgName(model.getSendOrgName());
		bean.setSendCompanyName(model.getSendCompanyName());
		bean.setSendCompanyId(model.getSendCompanyId());
		bean.setReceiveUserId(model.getReiceiveUserId());
		bean.setReceiveUserName(model.getReiceiveUserName());
		bean.setReceiveOrgId(model.getReceiveOrgId());
		bean.setReceiveOrgName(model.getReceiveOrgName());
		bean.setPrevActDefId(model.getHistoricTaskInstance().getPreTaskDefKey());
		bean.setPrevActDefName(model.getHistoricTaskInstance().getPreTaskDefName());
		bean.setPrevActInstId(model.getHistoricTaskInstance().getPreTaskId());
		bean.setCurActDefId(model.getHistoricTaskInstance().getTaskDefinitionKey());
		bean.setCurActDefName(model.getHistoricTaskInstance().getName());
		bean.setCurActInstId(model.getHistoricTaskInstance().getId());
		bean.setProcInstId(model.getHistoricTaskInstance().getProcessInstanceId());
		return bean;
	}
	
	public List<ProcessLogBean> buildProcessLogList(List<ProcessLogModel> list){
		List<ProcessLogBean> result = new ArrayList<ProcessLogBean>();
		for(ProcessLogModel model : list) {
			result.add(build(model));
		}
		return result;
	}
	
	public ActivityOpBean build(ActivityOperatePower model) {
		ActivityOpBean bean = new ActivityOpBean();
		BeanUtils.copyProperties(model, bean);
		return bean;
	}
	
	public List<ActivityOpBean> buildActOpList(List<ActivityOperatePower> list){
		List<ActivityOpBean> result = new ArrayList<ActivityOpBean>();
		for(ActivityOperatePower power : list) {
			result.add(build(power));
		}
		return result;
	}
	
	public ProcessInputModel convert2InputModel(ProcessInputBean bean) {
		ProcessInputModel model = new ProcessInputModel();
		model.setWf_procDefId(bean.getProcDefId());
		model.setWf_procTitle(bean.getTitle());
		model.setWf_businessKey(bean.getBusinessKey());
		model.setWf_sender(bean.getUserId());
		model.setWf_businessDataObject(bean.getDataObject());
		//model.setWf_dataObject(bean.getDataObject());
		model.setFields(bean.getFields());
		return model;
	}
	
	public SysGlTypeBean build(SysGlType model) {
		SysGlTypeBean bean = new SysGlTypeBean();
		bean.setTenantId(model.getAppKey());
		BeanUtils.copyProperties(model, bean);
		return  bean;
	}
	
	public List<SysGlTypeBean> buildTypeList(List<SysGlType> list){
		List<SysGlTypeBean> result = new ArrayList<SysGlTypeBean>();
		for(SysGlType type : list) {
			result.add(build(type));
		}
		return result;
	}
	
	public CommonIdeaBean build(CommonIdeaEntity model) {
		CommonIdeaBean bean = new CommonIdeaBean();
		BeanUtils.copyProperties(model, bean);
		return bean;
	}
	
	public List<CommonIdeaBean> buildCommIdeaList(List<CommonIdeaEntity> list){
		List<CommonIdeaBean> result = new ArrayList<CommonIdeaBean>();
		for(CommonIdeaEntity idea : list) {
			result.add(build(idea));
		}
		return result;
	}
}
