package com.cloudcross.ssp.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.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.cloudcross.ssp.base.dao.GenericIBatisDao;
import com.cloudcross.ssp.common.consts.DirectType;
import com.cloudcross.ssp.common.utils.AdvertiserScheduleAclsUtis;
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.SqlHelper;
import com.cloudcross.ssp.model.Acls;
import com.cloudcross.ssp.model.AdGroup;
import com.cloudcross.ssp.model.AdGroupPlace;
import com.cloudcross.ssp.model.AdGroupSchedule;
import com.cloudcross.ssp.model.AdgroupWifigroup;
import com.cloudcross.ssp.model.AdgroupZone;
import com.cloudcross.ssp.model.Direct;
import com.cloudcross.ssp.model.Location;
import com.cloudcross.ssp.service.IAdGroupPlaceService;
import com.cloudcross.ssp.service.IAdGroupScheduleService;
import com.cloudcross.ssp.service.IAdGroupService;
import com.cloudcross.ssp.service.IAdgroupWifigroupService;
import com.cloudcross.ssp.service.IAdgroupZoneService;
import com.cloudcross.ssp.service.IBannerService;
import com.cloudcross.ssp.service.IDirectService;
import com.cloudcross.ssp.service.ILocationService;
import com.cloudcross.ssp.web.widget.SelectorController.ISelector;
import com.cloudcross.ssp.web.widget.SelectorController.ISelectorProvider;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

@Service
public class AdGroupService implements IAdGroupService, ISelectorProvider {
	@Autowired
	private GenericIBatisDao myBatisDao;
	@Autowired
	private IAdGroupPlaceService adGroupPlaceService;
	@Autowired
	private ILocationService locationService;
	@Autowired
	private IAdGroupScheduleService adGroupScheduleService;
	@Autowired
	private IDirectService directService;
	@Autowired
	private IBannerService bannerService;
	@Autowired
	private IAdgroupZoneService adgroupZoneService;
	@Autowired
	private IAdgroupWifigroupService adgroupWifigroupService;
	@Override
	public AdGroup findById(Long id) {
		return myBatisDao.get("adGroupSqlMapper.findById", id);
	}

	@Override
	public int countByParams(Map<String, Object> paramMap) {
		return myBatisDao.get("adGroupSqlMapper.countByParams", paramMap);
	}

	@Override
	public List<AdGroup> findByParams(Map<String, Object> paramMap, Pager pager) {
		paramMap.put("pager", pager);
		return myBatisDao.getList("adGroupSqlMapper.findByParams", paramMap);
	}

	@Override
	public boolean add(AdGroup t) {
		myBatisDao.save("adGroupSqlMapper.addAdGroup", t);
		return true;
	}

	@Override
	public boolean edit(AdGroup t) {
		myBatisDao.save("adGroupSqlMapper.editAdGroup", t);
		return true;
	}

	@Override
	public boolean updateStatus(List<Long> idList, int status) {
		myBatisDao.save("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("adGroupSqlMapper.findByCampaignId", campaignId);
	}

	@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);
		//时间定向
		
		//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;
	}

	@Override
	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);
			}
		}
		
	}

	@Override
	public boolean updatedAdgroupSupdated(Long adGroupId) {
		myBatisDao.save("adGroupSqlMapper.updatedSupdated", adGroupId);
		return true;
	}

	@Override
	public List<AdGroup> findByParams(Map<String, Object> paramMap) {
		return myBatisDao.getList("adGroupSqlMapper.findByParams1", paramMap);
	}

	@Override
	public List<Long> findAllAdGroudByAdvertiserId(Long advertiserId) {
		return myBatisDao.getList("adGroupSqlMapper.findAllAdGroudByAdvertiserId", advertiserId);
	}

	@Override
	public boolean updateSupdatedByAdvertiserId(List<Long> advertiserIdList,
			Date date) {
		myBatisDao.save("adGroupSqlMapper.updateSupdatedByAdvertiserID",
				MapBuilder.create(HashMap.class)
					.add("advertiserIdList", advertiserIdList)
					.add("modifyDate", date).map());
		return true;
	}

	@Override
	public boolean updateSupdatedByOrderId(List<Long> orderIdList, Date date) {
		myBatisDao.save("adGroupSqlMapper.updateSupdatedByOrderId",
				MapBuilder.create(HashMap.class)
					.add("orderIdList", orderIdList)
					.add("modifyDate",date).map());
		return true;
	}

	@Override
	public boolean updateSupdatedByCampaignId(List<Long> campaignIdList,
			Date date) {
		myBatisDao.save("adGroupSqlMapper.updateSupdatedByCampaignId",
				MapBuilder.create(HashMap.class)
					.add("campaignIdList", campaignIdList)
					.add("modifyDate",date).map());	
		return true;
	}

	@Override
	public boolean updateStatusByAdvertiserId(List<Long> advertiserIdList,
			int status) {
		myBatisDao.save("adGroupSqlMapper.updateStatusByAdvertiserId",
				MapBuilder.create(HashMap.class)
					.add("advertiserIdList", advertiserIdList)
					.add("modifyDate", new Date())
					.add("status", status).map());
		return true;
	}

	@Override
	public boolean updateStatusByOrderId(List<Long> orderIdList, int status) {
		myBatisDao.save("adGroupSqlMapper.updateStatusByOrderId",
				MapBuilder.create(HashMap.class)
					.add("orderIdList", orderIdList)
					.add("modifyDate", new Date())
					.add("status", status).map());
		return true;
	}

	@Override
	public boolean updateStatusByCampaignId(List<Long> campaignIdList,
			int status) {
		myBatisDao.save("adGroupSqlMapper.updateStatusByCampaignId",
				MapBuilder.create(HashMap.class)
					.add("campaignIdList", campaignIdList)
					.add("modifyDate", new Date())
					.add("status", status).map());
		return true;
	}

	@Override
	public boolean updateStatusAll(List<Long> adGroupIdList, int status) {
		Boolean adGroupFlag = updateStatus(adGroupIdList, status);
		Boolean bannerFlag = this.bannerService.updateStatusByAdGroupId(adGroupIdList,status);
		return adGroupFlag&&bannerFlag;
	}

	@Override
	public Map findAreasBack(Long adGroupId) {
		return myBatisDao.get("adGroupSqlMapper.findAreasBack", adGroupId);
	}

	@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();
	}

	
public void commonSaveDriect(Map<String,Object> targetParamsMap,Map<String,Object> map){
		
		String uiKey = (String)map.get("uiKey");
		Integer uiType = (Integer) 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));
			// 将地域定向的数据转化为后台需要的数据格式
			if(uiType == DirectType.locateType) {
				direct.setData(front2dblocate((String) targetParamsMap.get(uiKey)));
			}
			
			if(uiType == DirectType.timeType) {
				// 将数据批量存入排期表
		        List<AdGroupSchedule> scheduleList = AdvertiserScheduleAclsUtis.getScheduleList(
		            adGroupId, (String) targetParamsMap.get(uiKey));
		        
		        //调用接口batchschedule  
		        adGroupScheduleService.batchAdd(scheduleList);
		        
		        //将时间排期的数据转化为后台需要的数据格式
		        String data = AdvertiserScheduleAclsUtis.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);
						//默认24个时间点
						String allHours = "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23";
						//如果传过来的dehours是-1或空或者是空字符串，表示全选
						if(null == obj.get("dehours") || "-1".equals(String.valueOf(obj.getString("dehours"))) ||
								"".equals(String.valueOf(obj.getString("dehours")))) {
							obj.put("dehours", allHours);
						} 
						
						result.put(obj);
					}
					direct.setBackShow(result.toString());
				} catch (JSONException e) {
					 direct.setBackShow(targetParamsMap.get("sdayParting").toString());
					e.printStackTrace();
				}
		       
			}
			
			direct.setDirectType(uiType);
			myBatisDao.save("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");
		Integer uiType = (Integer)map.get("uiType");
		AdGroup adGroup= (AdGroup)map.get("adGroup");
		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)){
			//删除数据库对应的历史数据
		    myBatisDao.delete("directSqlMapper.deleteDirect", MapBuilder.create(HashMap.class)
		    											.add("adGroupId", adGroup.getId())
		    											.add("directType",uiType)
		    											.map());
		    if(idList!=null){
		    	myBatisDao.delete("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));
				// 将地域定向的数据转化为后台需要的数据格式
				if(uiType == DirectType.locateType) {
					direct.setData(front2dblocate((String) targetParamsMap.get(uiKey)));
				}
				
		        if(uiType == DirectType.timeType) {
		         // 将数据批量存入排期表
		          List<AdGroupSchedule> scheduleList = AdvertiserScheduleAclsUtis.getScheduleList(
		              adGroup.getId(), (String) targetParamsMap.get(uiKey));
		         
		          //调用接口batchschedule
		          adGroupScheduleService.batchAdd(scheduleList);
		          String data = AdvertiserScheduleAclsUtis.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);
			  				//默认24个时间点
							String allHours = "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23";
							//如果传过来的dehours是-1或空或者是空字符串，表示全选
							if(null == obj.get("dehours") || "-1".equals(String.valueOf(obj.getString("dehours"))) ||
									"".equals(String.valueOf(obj.getString("dehours")))) {
								obj.put("dehours", allHours);
							} 
			  				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("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("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 {
				//处理定向没有设置的情况
			}
			
		}
		
	}	
	
		/**
		 * 把前台获取的数据转化成后台数据库需要的数据格式 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;
		}

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

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

		@Override
		public boolean saveAll(AdGroup adGroup, Map<String,Object> condition) {
			//添加投放，时间定向，地域定向
			save(adGroup,condition);
			Long adgroupId = adGroup.getId();
			Long supdated = new Date().getTime()/1000;
			//添加土方与广告位对应关系
			List<Long> zoneIdList = adGroup.getZoneIdList();
			if(zoneIdList != null && zoneIdList.size()>0){
				AdgroupZone adgroupZone = new AdgroupZone();
				adgroupZone.setAdgroupId(adgroupId);
				adgroupZone.setStatus(0);//开启状态
				adgroupZone.setSupdated(supdated);
				this.adgroupZoneService.saveAdgroupZone(adgroupZone,zoneIdList);
			}
			
			//添加投放于分组的对应关系
			List<Long> wifigroupIdList = adGroup.getWifigroupIdList();
			if(wifigroupIdList != null && wifigroupIdList.size()>0){
				AdgroupWifigroup adgroupWifigroup = new AdgroupWifigroup();
				adgroupWifigroup.setAdgroupId(adgroupId);
				adgroupWifigroup.setStatus(0);//开启状态
				adgroupWifigroup.setSupdated(supdated);
				this.adgroupWifigroupService.saveAdgroupWifigroup(adgroupWifigroup, wifigroupIdList);
			}
			
			//添加投放与数聚场景的对应关系
			List<Long> placeIdList = adGroup.getPlaceIdList();
			if(placeIdList != null && placeIdList.size()>0){
				AdGroupPlace adGroupPlace = new AdGroupPlace();
				adGroupPlace.setAdGroupId(adgroupId);
				adGroupPlace.setStatus(0);
				adGroupPlace.setSupdated(supdated);
				this.adGroupPlaceService.saveAdGroupPlace(adGroupPlace, placeIdList);
			}
			
			return false;
		}
		
		
}
