package com.xt.hb.data.cbyj.svcimpl;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.geom.PrecisionModel;
import com.xt.hb.data.aq.svc.AqcxService;
import com.xt.hb.data.cbyj.mapper.CbyjMapper;
import com.xt.hb.data.cbyj.model.Cbyj;
import com.xt.hb.data.service.FetchService;
import com.xt.hb.data.system.GlobalData;
import com.xt.hb.data.util.IdGenerator;
import com.yuanxd.tools.hscbdt.HscbdtService;
import com.yuanxd.tools.hscbdt.bean.SeqShips;
import com.yuanxd.tools.hscbdt.bean.Ship;
import com.yuanxd.tools.io.http.HttpResultType;
import com.yuanxd.tools.io.http.HttpUtil;
import com.yuanxd.tools.io.http.RequestBean;
import com.yuanxd.tools.io.http.ResponseBean;
import com.yuanxd.tools.utils.string.StringUtils;

/**
 * 船舶预警服务
 * 
 * @author 袁晓冬
 *
 */
@Service
public class CbyjService implements FetchService {
	private final Logger log = LoggerFactory.getLogger(CbyjService.class);
	private GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), 4326);
	@Autowired
	private HscbdtService hscbdtService;
	@Autowired
	private CbyjMapper cbyjMapper;
	@Autowired
	private IdGenerator idGenerator;
	@Autowired
	private AqcxService aqcxService;

	// 存放上次查询区域内船舶信息
	private Map<String, List<Ship>> currShipsMap = new HashMap<>();
	private Map<String, List<Ship>> tempShipMap = new HashMap<>();

	@Override
	public int doFetch() {
		RequestBean rb = new RequestBean(HttpResultType.STRING);
		rb.setUrl(GlobalData.CBYJ_URL);
		ResponseBean response = HttpUtil.getInstance().execute(rb);
		String result = response.getStringResult();
		Map<String, Polygon> areas = getPolygonFromResult(result);
		if (null == areas) {
			return 0;
		}
		for (Entry<String, Polygon> entry : areas.entrySet()) {
			analyseArea(entry.getKey(), entry.getValue());
		}
		return areas.size();
	}

	/**
	 * 分析一个多边形区域
	 * 
	 * @param id
	 * @param polygon
	 */
	private void analyseArea(String id, Polygon polygon) {
		Double maxX = null, maxY = null, minX = null, minY = null;
		for (Coordinate co : polygon.getCoordinates()) {
			if (null == maxX) {
				maxX = co.x;
			}
			if (null == maxY) {
				maxY = co.y;
			}
			if (null == minX) {
				minX = co.x;
			}
			if (null == minY) {
				minY = co.y;
				continue;
			}
			// 非空情况比较
			if (Double.compare(maxX, co.x) < 0) {
				maxX = co.x;
			}
			if (Double.compare(maxY, co.y) < 0) {
				maxY = co.y;
			}
			if (Double.compare(minX, co.x) > 0) {
				minX = co.x;
			}
			if (Double.compare(minY, co.y) > 0) {
				minY = co.y;
			}
		}
		// 获取ais数据
		SeqShips ships = hscbdtService.searchObjectResultByArea(0, minX + "," + minY, maxX + "," + maxY);
		if (null == ships) {// 没获取到数据
			return;
		}
		List<Ship> currShips = currShipsMap.get(id);
		List<Ship> tempShips = tempShipMap.get(id);
		// 首次分析
		if (null == currShips) {
			log.info("首次分析区域{}", id);
			currShips = new ArrayList<>();
			for (Ship ship : ships.getShips()) {
				// 船舶位置
				Point cbwz = geometryFactory.createPoint(new Coordinate(ship.getLon(), ship.getLat()));
				if (polygon.contains(cbwz)) {
					// 船舶当前在围栏内，加入缓存
					currShips.add(ship);
				}
			}
			currShipsMap.put(id, currShips);
			// temp初始化
			tempShips = new ArrayList<>();
			tempShipMap.put(id, tempShips);
		} else {
			// 清空缓存，缓存存放本次区域内船舶
			tempShips.clear();
			for (Ship ship : ships.getShips()) {
				// 船舶位置
				Point cbwz = geometryFactory.createPoint(new Coordinate(ship.getLon(), ship.getLat()));
				if (polygon.contains(cbwz)) {
					tempShips.add(ship);
					// 新船进入区域
					if (!currShips.contains(ship)) {
						Cbyj cbyj = new Cbyj();
						cbyj.setId(idGenerator.generateStringId());
						cbyj.setCm(getZwcmByYwcm(ship));
						cbyj.setMmsi(ship.getMmsi());
						cbyj.setLx("1");
						cbyj.setYjsj(new Date());
						cbyj.setArea(id);
						cbyjMapper.insert(cbyj);
						aqcxService.saveCbyjgg(cbyj);
					}
				}
			}
			for (Ship ship : currShips) {
				// 船舶离开区域
				if (!tempShips.contains(ship)) {
					Cbyj cbyj = new Cbyj();
					cbyj.setId(idGenerator.generateStringId());
					cbyj.setCm(getZwcmByYwcm(ship));
					cbyj.setMmsi(ship.getMmsi());
					cbyj.setLx("0");
					cbyj.setYjsj(new Date());
					cbyj.setArea(id);
					cbyjMapper.insert(cbyj);
					aqcxService.saveCbyjgg(cbyj);
				}
			}
			// 新的当前船舶集合
			currShipsMap.put(id, tempShips);
			// 清空老集合作为缓存集合
			currShips.clear();
			tempShipMap.put(id, currShips);
		}

	}

	/**
	 * 从结果中获取面数据
	 * 
	 * @param result
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private Map<String, Polygon> getPolygonFromResult(String result) {
		if (null == result) {
			return null;
		}
		ObjectMapper objectMapper = new ObjectMapper();
		Map<String, Object> map = null;
		try {
			map = objectMapper.readValue(result, Map.class);
		} catch (Exception e) {
			e.printStackTrace();
		}
		List<Map> features = (List) map.get("features");
		Map<String, Polygon> areas = new HashMap<>();
		for (Map m : features) {
			Map attributes = (Map) m.get("attributes");
			Map geometry = (Map) m.get("geometry");
			List<List<Double>> rings = (List) ((List) geometry.get("rings")).get(0);
			Polygon area = getPolygonFromPoints(rings);
			areas.put(String.valueOf(attributes.get("ID")), area);
		}
		return areas;
	}

	/**
	 * 根据点位创建区域
	 * 
	 * @param rings
	 * @return
	 */
	private Polygon getPolygonFromPoints(List<List<Double>> rings) {
		Coordinate[] coordinates = new Coordinate[rings.size()];
		int index = 0;
		for (List<Double> ps : rings) {
			coordinates[index++] = new Coordinate(ps.get(0), ps.get(1));
		}
		Polygon polygon = new GeometryFactory().createPolygon(coordinates);
		return polygon;
	}

	@Override
	public String getName() {
		return "船舶预警服务";
	}

	static class MapPoint {
		// 纬度
		Double lat;
		// 经度
		Double lon;

		public Double getLat() {
			return lat;
		}

		public void setLat(Double lat) {
			this.lat = lat;
		}

		public Double getLon() {
			return lon;
		}

		public void setLon(Double lon) {
			this.lon = lon;
		}
	}

	/**
	 * 根据英文船名查找中文船名
	 * 
	 * @param ywcm
	 * @return
	 */
	private String getZwcmByYwcm(Ship ship) {
		String ywcm = ship.getName();
		if (StringUtils.isEmpty(ywcm)) {
			return ship.getMmsi();
		}
		List<String> zwcms = cbyjMapper.selectCbmcByEnName(ywcm.replaceAll(" ", ""));
		if (zwcms == null || zwcms.size() == 0) {
			return ywcm;
		} else {
			if (StringUtils.isEmpty(zwcms.get(0))) {
				return ywcm;
			}
			return zwcms.get(0);
		}
	}

	@Override
	public String message() {
		return "共扫描区域数：" + currShipsMap.size();
	}
}
