package com.cloudcross.ssp.back.service.impl;

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

import org.apache.commons.lang.ArrayUtils;
import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.cloudcross.ssp.back.model.Acls;
import com.cloudcross.ssp.back.model.AdGroup;
import com.cloudcross.ssp.back.model.AdGroupPlace;
import com.cloudcross.ssp.back.model.AdGroupSchedule;
import com.cloudcross.ssp.back.model.Direct;
import com.cloudcross.ssp.back.model.Location;
import com.cloudcross.ssp.back.service.IAdGroupPlaceService;
import com.cloudcross.ssp.back.service.IAdGroupScheduleService;
import com.cloudcross.ssp.back.service.IAdGroupService;
import com.cloudcross.ssp.back.service.IDirectService;
import com.cloudcross.ssp.back.service.ILocationService;
import com.cloudcross.ssp.base.dao.GenericIBatisDao;
import com.cloudcross.ssp.common.consts.DirectType;
import com.cloudcross.ssp.common.utils.Assert;
import com.cloudcross.ssp.common.utils.MapBuilder;
import com.cloudcross.ssp.common.utils.Pager;
import com.cloudcross.ssp.common.utils.ScheduleAclsUtis;
import com.cloudcross.ssp.common.utils.SqlHelper;
import com.cloudcross.ssp.web.widget.SelectorController.ISelector;
import com.cloudcross.ssp.web.widget.SelectorController.ISelectorProvider;



@Service
public class AdGroupService implements IAdGroupService, ISelectorProvider {
	
	private static final Logger LOG = Logger.getLogger(AdGroupService.class);
	
	@Autowired
	private GenericIBatisDao myBatisDao;
	@Autowired
	private IAdGroupPlaceService adGroupPlaceService;
	@Autowired
	private ILocationService locationService;
	@Autowired
	private IAdGroupScheduleService adGroupScheduleService;
	@Autowired
	private IDirectService directService;
	
	@Override
	public AdGroup findById(Long id) {
		return myBatisDao.get("back.adGroupSqlMapper.findById", id);
	}

	@Override
	public int countByParams(Map<String, Object> paramMap) {
		//这里的搜索只是对投放名称进行搜索
		String searchValue = SqlHelper.doLike(paramMap.get("adGroupName"));
		paramMap.put("adGroupName", searchValue);
		return myBatisDao.get("back.adGroupSqlMapper.countByParams", paramMap);
	}

	@Override
	public List<AdGroup> findByParams(Map<String, Object> paramMap, Pager pager) {
		//这里的搜索只是对投放名称进行搜索
		String searchValue = SqlHelper.doLike(paramMap.get("adGroupName"));
		paramMap.put("adGroupName", searchValue);
		paramMap.put("pager", pager);
		return myBatisDao.getList("back.adGroupSqlMapper.findByParams", paramMap);
	}
	/**
	 * 找到所有的已选的排期和地域
	 */
	public Map findAreas(Long adGroupId) {
		return myBatisDao.get("back.adGroupSqlMapper.findAreas", adGroupId);
	}

	@Override
	public boolean add(AdGroup t) {
//		Date now = new Date();
//		t.setCreateDate(now);
//		t.setModifyDate(now);
		myBatisDao.save("back.adGroupSqlMapper.addAdGroup", t);
		return true;
	}

	@Override
	public boolean edit(AdGroup t) {
//		t.setModifyDate(new Date());
		myBatisDao.save("back.adGroupSqlMapper.editAdGroup", t);
		return true;
//		return false;
	}
	
	@Override
	public boolean updatedAdgroupSupdated(Long adGroupId) {
		// TODO Auto-generated method stub
		myBatisDao.save("back.adGroupSqlMapper.updatedSupdated",adGroupId);
		return true;
	}

	@Override
	public boolean updateStatus(List<Long> idList, int status) {
		myBatisDao.save("back.adGroupSqlMapper.updateAdGroupStatus",MapBuilder.create(HashMap.class)
				.add("status", status)
				.add("idList", idList)
				.add("updated", new Date())
				.map());
		return true;
	}

	@Override
	public List<AdGroup> findByCampaignId(Long campaignId) {
		return myBatisDao.getList("back.adGroupSqlMapper.findByCampaignId", campaignId);
	}

	@Override
	public Map<String, List<? extends ISelector>> provideData(String[] parentId) {
		Assert.isTrue(ArrayUtils.isNotEmpty(parentId));
		String campaignId = parentId[0];
		List<AdGroup> adGroupList = findByCampaignId(Long.parseLong(campaignId));
		return MapBuilder.create(HashMap.class).add(campaignId, adGroupList)
				.map();
	}

	@Override
	public boolean save(AdGroup adGroup, Map<String, Object> targetParamsMap) {
		//创建策略
		add(adGroup);
		
		//处理带定向的问题
		MapBuilder mapBuilder = MapBuilder.create(HashMap.class).add("adGroup", adGroup);
		//地域定向
		commonSaveDriect(targetParamsMap, mapBuilder.add("uiKey", "areas")
													.add("uiType",DirectType.locateType)
													.map());
		//时间定向
		commonSaveDriect(targetParamsMap, mapBuilder.add("uiKey","dayParting")
													.add("uiType",DirectType.timeType)
													.map());
													
		return true;
	}
	@Override
	public boolean edit(AdGroup adGroup, Map<String, Object> targetParamsMap) {
		edit(adGroup);
		
		/**
		 * 时段定向的数据更新
		 */
		//先删除原来的信息
		adGroupScheduleService.deleteByAdGroupId(adGroup.getId());
//		directService.deleteByadGroupId(adGroup.getId(), DirectType.timeType);
		
		//处理带定向的问题
//		MapBuilder mapBuilder = MapBuilder.create(HashMap.class).add("adGroup", adGroup);
		//时间定向
		
		LOG.debug("目标键值对数据："+targetParamsMap.toString()+"------"+((String)targetParamsMap.get("areas")).equalsIgnoreCase(""));
		//banner 表的compiledLimitation aclPlugins字段 默认值是  "true"  null
		StringBuilder  compiledLimitationStr=new StringBuilder();
		StringBuilder  aclPluginsStr=new StringBuilder();
		//获取策略下的所有创意
//		List<Ad> adList = myBatisDao.getList("adSqlMapper.findByParams", MapBuilder.create(HashMap.class)
//														.add("adGroupId",adGroup.getId())
//														.map());
		List<Long> idList = null;
		//把创意List的id保存到idList
//		if(adList!=null&&adList.size()>0) {
//			idList = new ArrayList<Long> ();
//			for (Ad tempAd : adList) {
//				idList.add(tempAd.getId());
//			}
//		}
		//公共的参数
		MapBuilder mapBuilder = MapBuilder.create(HashMap.class).add("adGroup", adGroup)
																.add("idList", idList)
																.add("compiledLimitationStr", compiledLimitationStr)
																.add("aclPluginsStr",aclPluginsStr);
		//添加策略通用处理方法
		//地域定向	
		commonEditDirect(targetParamsMap, mapBuilder.add("uiKey", "areas")
												.add("uiType",DirectType.locateType)
												.add("logical","and")
												.add("comparison","=x")
												.add("suffix", new String[] { "MAX_checkGeo_City('","', '=x')"})
											    .map());
		commonEditDirect(targetParamsMap, mapBuilder.add("uiKey", "dayParting")
												.add("uiType",DirectType.timeType)
												.add("logical","and")
												.add("comparison","=~")
												.add("suffix", new String[] { "MAX_checkTime_Day('","', '=~')"})
											    .map());
		
		//修改创意的字段
		//修改创意的compiledLimitation aclPluginsStr的字段
		if(idList!=null){
			if(compiledLimitationStr.length()<=0){
				myBatisDao.save("adSqlMapper.editBatch", MapBuilder.create(HashMap.class)
											 .add("compiledLimitation","true")
											 .add("aclPlugins",null)
											 .add("idList",idList)
											 .map());
			}else {
				myBatisDao.save("adSqlMapper.editBatch", MapBuilder.create(HashMap.class)
						 .add("compiledLimitation", compiledLimitationStr.toString())
						 .add("aclPlugins",aclPluginsStr.toString())
						 .add("idList",idList)
						 .map());
			}
			
		}else {
			
		}
		
		return true;
	}
	
public void commonSaveDriect(Map<String,Object> targetParamsMap,Map<String,Object> map){
		
		String uiKey = (String)map.get("uiKey");
		String uiType = (String) map.get("uiType");
		AdGroup adGroup= (AdGroup)map.get("adGroup");
		Long adGroupId = adGroup.getId();
		
		if (targetParamsMap != null && targetParamsMap.containsKey(uiKey)
				&& !targetParamsMap.get(uiKey).equals("")) {
			// 添加地域 rv_traget_show
			Direct direct = new Direct();
			direct.setAdGroupId(adGroup.getId());
			direct.setBackShow((String) targetParamsMap.get(uiKey));
			// 把前台数据转化为后台需要的数据格式
			direct.setData(front2db((String) targetParamsMap.get(uiKey),uiType));
			
			if(uiType.equalsIgnoreCase(DirectType.timeType)) {
				// 将数据批量存入排期表
		        List<AdGroupSchedule> scheduleList = ScheduleAclsUtis.getScheduleList(
		            adGroupId, (String) targetParamsMap.get(uiKey));
		        
		        //调用接口batchschedule  
		        adGroupScheduleService.batchAdd(scheduleList);
		        String data = ScheduleAclsUtis.scheduleRoleStr(scheduleList);
		        if(data != null && data.trim() != ""){
		        	data = data.concat("@Asia/Shanghai");
		        }
		        direct.setData(data);
		        try {
					JSONArray sdayParting = new  JSONArray(targetParamsMap.get("sdayParting").toString());
					JSONArray result = new JSONArray();
					for (int i = 0; i < sdayParting.length(); i++) {
						JSONObject obj = (JSONObject) sdayParting.get(i);
						result.put(obj);
					}
					direct.setBackShow(result.toString());
				} catch (JSONException e) {
					 direct.setBackShow(targetParamsMap.get("sdayParting").toString());
					e.printStackTrace();
				}
		       
			}
			
			direct.setDirectType(uiType);
			myBatisDao.save("back.directSqlMapper.addDirect", direct);
		}
	}
	
	// uiKey地域： "areas" uiType地域： DirectType.locateType
	//targetParamsMap 前台UI传入的表单
	public void commonEditDirect(Map<String,Object> targetParamsMap,Map<String,Object> map){

		String uiKey = (String)map.get("uiKey");
		String uiType = (String)map.get("uiType");
		AdGroup adGroup= (AdGroup)map.get("adGroup");
		System.out.println((String)map.get(uiKey)+">>>>");
		List<Long> idList = (List<Long>) map.get("idList");
		String logical = (String) map.get("logical");
		String comparison = (String)map.get("comparison");
		StringBuilder compiledLimitationStr=(StringBuilder) map.get("compiledLimitationStr");
		String [] suffix=(String[]) map.get("suffix");
		StringBuilder aclPluginsStr=(StringBuilder) map.get("aclPluginsStr");
		//处理策略 地域定向的情况
		if(targetParamsMap.containsKey(uiKey)){
			System.out.println("HelloWorld!");
			//删除数据库对应的历史数据
		    myBatisDao.delete("back.directSqlMapper.deleteDirect", MapBuilder.create(HashMap.class)
		    											.add("adGroupId", adGroup.getId())
		    											.add("directType",uiType)
		    											.map());
		    if(idList!=null){
		    	myBatisDao.delete("back.aclsSqlMapper.deleteAclsBatch", MapBuilder.create(HashMap.class)
						.add("idList", idList)
						.add("type",uiType)
						.map());	
		    }
			
			if(!((String)targetParamsMap.get(uiKey)).equalsIgnoreCase("")){
				//添加对应的定向数据 
				Direct direct = new Direct();
				direct.setAdGroupId(adGroup.getId());
				direct.setBackShow((String) targetParamsMap.get(uiKey));
				System.out.println(front2db((String) targetParamsMap.get(uiKey),uiType)+"mmmmmm");
				// 把前台数据转化为后台需要的数据格式
				direct.setData(front2db((String) targetParamsMap.get(uiKey),uiType));
				
				//注释掉排期注释代码
		        if(uiType.equalsIgnoreCase(DirectType.timeType)) {
		         // 将数据批量存入排期表
		          List<AdGroupSchedule> scheduleList = ScheduleAclsUtis.getScheduleList(
		              adGroup.getId(), (String) targetParamsMap.get(uiKey));
		         
		          //调用接口batchschedule
		          adGroupScheduleService.batchAdd(scheduleList);
		          String data = ScheduleAclsUtis.scheduleRoleStr(scheduleList);
		          if(data != null && data.trim() != ""){
		          	data = data.concat("@Asia/Shanghai");
		          }
		          direct.setData(data);
		          try {
			  			JSONArray sdayParting = new  JSONArray(targetParamsMap.get("sdayParting").toString());
			  			JSONArray result = new JSONArray();
			  			for (int i = 0; i < sdayParting.length(); i++) {
			  				JSONObject obj = (JSONObject) sdayParting.get(i);
			  				if(obj.has("dehours") && (obj.getString("dehours").equals("-1") || "".equals(obj.getString("dehours").trim()))){
			  					obj.remove("dailyImpression");
			  					obj.put("dailyImpression", "0");
			  				}
			  				result.put(obj);
			  			}
			  			direct.setBackShow(result.toString());
			  		} catch (JSONException e) {
			  			 direct.setBackShow(targetParamsMap.get("sdayParting").toString());
			  			e.printStackTrace();
			  		}
		        /*  data = data.concat("@Asia/Shanghai");
		          direct.setData(data);
		          direct.setBackShow(targetParamsMap.get("sdayParting").toString());*/
		        }
				
				direct.setDirectType(uiType);
				myBatisDao.save("back.directSqlMapper.addDirect", direct);
				//增加对应策略下的acls数据
					if(idList!=null) {
							Acls acls = new Acls();
							acls.setLogical(logical);
							acls.setType(direct.getDirectType());
							acls.setComparison(comparison);
							acls.setData(direct.getData());
							acls.setAdGroupId(adGroup.getId());
							myBatisDao.save("back.aclsSqlMapper.addAclsBatch",MapBuilder.create(HashMap.class)
																						.add("idList",idList)
																						.add("acls",acls)
																						.add("adGroupId", adGroup.getId())
																						.map());
 							if(compiledLimitationStr.length()<=0){
 								 compiledLimitationStr.append(suffix[0]+ direct.getData() +suffix[1]);
						    	 aclPluginsStr.append(direct.getDirectType());
 							}else {
 								 compiledLimitationStr.append(" and "+suffix[0]+ direct.getData() +suffix[1]);
						    	 aclPluginsStr.append(","+direct.getDirectType());
 							}
							
									}
			}else {
				//处理定向没有设置的情况
			}
			
		}
		
	}	
	private String front2db(String data ,String directType){
	
		if(DirectType.locateType.equalsIgnoreCase(directType)){
	
			return 	front2dblocate(data);
			
		}else if(DirectType.timeType.equalsIgnoreCase(directType)){
			
			return  front2dbTime(data);
		}else if(DirectType.osType.equalsIgnoreCase(directType)){
			//目前什么也不做，直接返回数据
			return data;
		}else if(DirectType.browserType.equalsIgnoreCase(directType)){
			//目前什么也不做，直接返回数据
			return  data;
		}				
		return null;
	}
	
	/**
	 * @param dateTime
	 *            页面传入JSON的日期的数据格式
	 *            {"Monday":{"display":[],"value":[]},"Tuesday":
	 *            {"display":[[2,4],[11,11]],"value":[[2],[3],[4],[11]]},
	 *            "Wednesday"
	 *            :{"display":[],"value":[]},"Thursday":{"display":[],
	 *            "value":[]},
	 *            "Friday":{"display":[],"value":[]},"Saturday":{"display"
	 *            :[],"value":[]},"Sunday":{"display":[],"value":[]}}
	 * @return 转化成数据库需要的数据格式 0_9,0_11,1_11,1_12,2_8,2_9,3_15,3_16
	 */
	private  static  String front2dbTime(String dateTime) {

		String[] days = { "Sunday", "Monday", "Tuesday", "Wednesday",
				"Thursday", "Friday", "Saturday" };
		if (dateTime != null) {
			StringBuilder sb = new StringBuilder();
			try {
				JSONObject jObject = new JSONObject(dateTime);
				for (int i = 0; i < 7; i++) {
					if (!jObject.getJSONObject(days[i]).getString("value")
							.equals("[]")) {
						String tmp = jObject.getJSONObject(days[i]).getString(
								"value");
						String[] strs = tmp.substring(1, tmp.length() - 1)
								.split(",");
						for (int j = 0; j < strs.length; j++) {
							if (sb.length() <= 0) {
								sb.append(i + "_" + strs[j].substring(1, strs[j].length()-1));
							} else {
								sb.append("," + i + "_" + strs[j].substring(1, strs[j].length()-1));
							}
						}
					}
				}
				sb.append("@Asia/Shanghai");
				return sb.toString();
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
		return null;
	}
	
	/**
	 * 把前台获取的数据转化成后台数据库需要的数据格式 CN|/CNXAXA00|CNSHSH00|CNBJBJ00|CNAHHZ00/
	 */
	private String front2dblocate(String str) {

		if (null != str) {
			StringBuilder sb = new StringBuilder();
			sb.append("CN|/");
			String[] strArr = str.split(",");
			for (String tmp : strArr) {
				if (tmp.length() == 6) {
					sb.append(tmp + "00|");
				} else if (tmp.length() == 4) {
					ArrayList<Location> locateList = (ArrayList<Location>) locationService
							.findByProvince(tmp);
					if (null != locateList) {
						for (Location locate : locateList) {
							sb.append(locate.getLocationT() + "|");
						}
					}
				}
			}
			sb.deleteCharAt(sb.length() - 1);
			sb.append("/");
			return sb.toString();
		}
		return null;
	}
	
	public void front2dbplace(String str,AdGroup adGroup) {
		AdGroupPlace adGroupPlace = new AdGroupPlace();
		if(null != str) {
			String[] strArr = str.split(",");
			for(int i = 0; i < strArr.length; i++) {
				adGroupPlace.setPlaceId(Long.valueOf(strArr[i]).longValue());
				adGroupPlace.setAdGroupId(adGroup.getId());
				adGroupPlaceService.add(adGroupPlace);
			}
		}
	}

}
