package com.yeejoin.amos.iec104.business.service.impl;

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

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import com.yeejoin.amos.connect.dao.entity.ClientListenVo;
import com.yeejoin.amos.connect.dao.entity.ConfigVo;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;

import com.yeejoin.amos.iec104.business.dao.repository.IClientListenDao;
import com.yeejoin.amos.iec104.business.dao.repository.IServiceConfDao;
import com.yeejoin.amos.iec104.business.param.AlarmParam;
import com.yeejoin.amos.iec104.business.service.intfc.IClientListenService;

@Service
public class ClientListenServiceImpl implements IClientListenService {
	@Autowired
	IClientListenDao iClientListenDao;
	@Autowired
    private IServiceConfDao iServiceConfDao;
	
	@Override
	@Transactional
	public void del(Long id) {
		iClientListenDao.delete(id);
	}

	@Override
	@Transactional
	public void add(ClientListenVo vo) {
		iClientListenDao.save(vo);
	}

	@Override
	public ClientListenVo findById(Long id) {
		return iClientListenDao.findOne(id);
	}

	@Override
	public void edit(ClientListenVo vo) {
		
	}

	@Override
	public ClientListenVo findOne(ClientListenVo vo) {
		return iClientListenDao.findOne(getSpecification(vo));
	}

	@Override
	public List<ClientListenVo> findAll(ClientListenVo vo) {
		return iClientListenDao.findAll(getSpecification(vo));
	}

	@Override
	public void sendDatas(String dataType, LinkedList<AlarmParam> params) {
		List<ConfigVo> clinets = iServiceConfDao.findAllByServiceType("IEC_SERVER");
		RestTemplate restTemplate = new RestTemplate();
		HttpHeaders headers = new HttpHeaders();
	    headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
		for (ConfigVo c : clinets) {
			HashMap<String, Object> param = new HashMap<>();
			param.put("dataType", dataType);
			param.put("channleNo", c.getChannelNo());
			List<ClientListenVo> clientList = iClientListenDao.findAll(getSpecification(param));
			for (ClientListenVo vo : clientList) {
				if (ObjectUtils.isEmpty(vo.getUrl())) {
					continue;
				}
			    
			    LinkedList<AlarmParam> list = filter(params, (p) -> p.getServiceId().equals(c.getServiceId()));
			    HttpEntity<LinkedList<AlarmParam>> request = new HttpEntity<>(list, headers);
			    try {
			    	restTemplate.postForEntity( vo.getUrl(), request , String.class );
				} catch (Exception e) {
				}
			    
			}
		}
	}
	
	public static LinkedList<AlarmParam> filter(List<AlarmParam> clints, java.util.function.Predicate<AlarmParam> condition) {
		LinkedList<AlarmParam> results = new LinkedList<AlarmParam>();
		for (AlarmParam c : clints) {
			if(condition.test(c)) {
				results.add(c);
	        }
		}
		return results;
	}
	
	@Override
	public void sendData(String dataType, String channelNo, AlarmParam params) {
		RestTemplate restTemplate = new RestTemplate();
		HashMap<String, Object> param = new HashMap<>();
		param.put("dataType", dataType);
		param.put("channleNo", channelNo);
		List<ClientListenVo> clientList = iClientListenDao.findAll(getSpecification(param));
		for (ClientListenVo vo : clientList) {
			if (ObjectUtils.isEmpty(vo.getUrl())) {
				continue;
			}
		    HttpHeaders headers = new HttpHeaders();
		    headers.setContentType(MediaType.APPLICATION_JSON_UTF8);

		    HttpEntity<AlarmParam> request = new HttpEntity<>(params, headers);
		    try {
		    	Logger.getLogger(this.getClass()).debug("send "+dataType+" data to " + vo.getUrl() + " . param is" + params.toString());
		    	 restTemplate.postForEntity( vo.getUrl(), request , String.class );
//		    	 restTemplate.postForEntity( "http://172.16.10.183:8083/api/risksource/data/fireqeuiment/soe", request , String.class );
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 *	 根据任务id构建查询任务回复信息查询条件
	 * @param
	 * @return Specification
	 */
	private Specification getSpecification(ClientListenVo vo) {
		return new Specification<ClientListenVo>() {  // 构建查询条件
			@Override
			public Predicate toPredicate(Root<ClientListenVo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				 List<Predicate> predicate = new ArrayList<>();
				 if (!ObjectUtils.isEmpty(vo.getChannleNo())) {
					 predicate.add(cb.equal(root.get("channleNo").as(String.class), vo.getChannleNo()));
				 }
				 if (!ObjectUtils.isEmpty(vo.getDataType())) {
					 predicate.add(cb.equal(root.get("dataType").as(String.class), vo.getDataType()));
				 }
				 if (!ObjectUtils.isEmpty(vo.getUrl())) {
					 predicate.add(cb.equal(root.get("url").as(String.class), vo.getUrl()));
				 }
				 Predicate[] pre = new Predicate[predicate.size()];
				 return query.where(predicate.toArray(pre)).getRestriction();
			}
		};
	}
	
	private Specification getSpecification(Map<String, Object> param) {
		return new Specification<ClientListenVo>() {  // 构建查询条件
			@Override
			public Predicate toPredicate(Root<ClientListenVo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				 List<Predicate> predicate = new ArrayList<>();
				 for (String key: param.keySet()) {
					 predicate.add(cb.equal(root.get(key).as(String.class), param.get(key)+""));
				 }
				 Predicate[] pre = new Predicate[predicate.size()];
				 return query.where(predicate.toArray(pre)).getRestriction();
			}
		};
	}

	@Override
	public List<ClientListenVo> getDataByServiceId(String serviceId) {
		ConfigVo vo = iServiceConfDao.findOneByServiceId(serviceId);
		HashMap<String, Object> param = new HashMap<>();
		param.put("channleNo", vo.getChannelNo());
		return iClientListenDao.findAll(getSpecification(param));
	}

	
}
