package com.ibeetl.admin.core.util.beetl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.beetl.core.Context;
import org.beetl.core.Function;
import org.beetl.sql.core.engine.SQLParameter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.ibeetl.admin.core.entity.CoreRoleFunction;
import com.ibeetl.admin.core.entity.CoreUser;
import com.ibeetl.admin.core.rbac.DataAccess;
import com.ibeetl.admin.core.rbac.DataAccessFactory;
import com.ibeetl.admin.core.rbac.DataAccessResullt;
import com.ibeetl.admin.core.service.CorePlatformService;
import com.ibeetl.admin.core.util.FunctionLocal;

/**
 * 数据权限拼sql，配合DataAccessFactory
 * @author lijiazhi
 *
 */
@Component
public class DataAccessFunction implements Function {
	
	Log log = LogFactory.getLog(DataAccessFunction.class);
	
	@Autowired
	CorePlatformService platFormService;
	@Autowired
	DataAccessFactory dataAccessFactory;
	
	private static Map defaultTargets = new HashMap();
	static{
		//数据库默认的跟组织和用户相关字段
		defaultTargets.put("org", "org_id");
		defaultTargets.put("user", "user_id");
	}
	private static final String 	SQL_MY_DATA = "user_id=? ";
	private static final String 	SQL_MY_ORG_DATA = "org_id=? ";
	

	
	public Object call(Object[] paras, Context ctx){
		//项目初期，总是返回1==1，避免数据权限带来的麻烦 
		CoreUser user = platFormService.getCurrentUser(); 
		//{"org":"org_id","user","user_id"}
		Map targets  = this.defaultTargets;
		//用户调用conroller 结果"user.view"
		String functionCode  = FunctionLocal.get();	
		
		if(paras.length==1){
			Object o = paras[0];
			if(o instanceof String){
				functionCode = (String)o;
			}else if(o instanceof Map){
				targets  = (Map)paras[1];
			}
		}else if(paras.length==2){
			functionCode = (String)paras[0];
			targets  = (Map)paras[1];
		}
		
		
		
		if(platFormService.isSupperAdmin(user)){
			return " 1=1 /* admin */ ";
		}
		Long currentOrgId = platFormService.getCurrentOrgId();
		
		List<CoreRoleFunction> roleFuns = platFormService.getRoleFunction(user.getId(),currentOrgId,functionCode);
		if(roleFuns.isEmpty()){
			//如果没有配置数据权限，是1=1,因此为角色指定功能的时候，需要设定数据权限，否则查询到所有数据
			return "1=1 /*empty data access */ ";
		}
		
		
		
		List<Object> list = (List<Object>)ctx.getGlobal("_paras");
		StringBuilder sb = new StringBuilder("  ");
		//数据权限范围划定
		boolean hasAppend = false;
		for(int i=0;i<roleFuns.size();i++){
			CoreRoleFunction fun = roleFuns.get(i);
			Integer accessType = fun.getDataAccessType();
			if(accessType==null){
				continue;
			}
			if(hasAppend){
				sb.append(" or ");
			}
			hasAppend = true;
			DataAccess data = dataAccessFactory.getDataAccess(accessType);
			DataAccessResullt ret = data.getOrg(user.getId(), currentOrgId);
			
			switch(ret.getStatus()){
			case NoneOrg:{
				sb.append(targets.get("org")+" in (-1) ");
				break;
			}
			case AllOrg:{
				//sql 不包含组织机构过滤信息
				continue ;
			}
			case OnlyUser:{
				List<Long> ids = ret.getUserIds();
				sb.append(targets.get("user"));
				if(ids.size()==0){
					sb.append("=-1/*指定用户，但没有候选用户*/");
					continue;
				}
					
				if(ids.size()==1){
					sb.append(" =? ");
					list.add(new SQLParameter(ids.get(0)));
					continue;
				}
				sb.append(" in (");
				for(int z=0;z<ids.size();z++){
					sb.append(" ? ");
					list.add(new SQLParameter(ids.get(z)));
					if(z!=ids.size()-1){
						sb.append(",");
					}
				}
				sb.append(") ");
				break;
			
			}
			case OnlyOrg:{
				List<Long> ids = ret.getOrgIds();
				sb.append(targets.get("org"));
				if(ids.size()==0){
					sb.append("=-1/*指定机构，但没有候选机构*/");
					continue;
				}
					
				if(ids.size()==1){
					sb.append(" =? ");
					list.add(new SQLParameter(ids.get(0)));
					continue;
				}
				sb.append(" in (");
				for(int z=0;z<ids.size();z++){
					sb.append("?");
					list.add(new SQLParameter(ids.get(z)));
					if(z!=ids.size()-1){
						sb.append(",");
					}
				}
				sb.append(") ");
				break;
			}
			default:{
				log.warn("错误的"+ret.getStatus().toString());
				throw new UnsupportedOperationException(ret.getStatus().toString());
			}
			}

			
		}
		
		
		return sb.toString();
	}
	

	
	
}
