package com.persagy.proxy.report.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.persagy.dmp.common.constant.ResponseCode;
import com.persagy.dmp.common.helper.SpringHelper;
import com.persagy.proxy.adm.constant.AdmRelationTypeEnum;
import com.persagy.proxy.adm.request.AdmDCSQueryRequest;
import com.persagy.proxy.adm.request.AdmQueryCriteria;
import com.persagy.proxy.adm.request.AdmResponse;
import com.persagy.proxy.adm.utils.AdmContextUtil;
import com.persagy.proxy.adm.utils.GeoToolsUtil;
import com.persagy.proxy.common.entity.InstanceUrlParam;
import com.persagy.proxy.object.model.AdmEquipment;
import com.persagy.proxy.object.model.AdmISpace;
import com.persagy.proxy.object.model.AdmSpace;
import com.persagy.proxy.object.model.AdmSystem;
import com.persagy.proxy.object.service.*;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.QueryParam;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 *
 * @version 1.0.0
 * @company persagy
 * @author zhangqiankun
 * @date 2021年10月18日 上午10:55:24
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/space")
public class AdmSpaceInfoController {

	private final IAdmISpaceService ispaceService;
	private final IAdmFloorService floorService;
	private final IAdmSystemService systemService;
	private final IAdmEquipmentService equipmentService;
	private final IAdmSpaceService spaceService;

	/**
	 * 统计 属于多建筑楼层的空间
	 *
	 * @param request
	 * @return
	 */
	@RequestMapping("/space-bd-fl")
	public JSONObject queryCount(HttpServletRequest request) {
		Set<String> spaceIds = spaceService.queryMultiBuildingOrFloorSpaceIds(request);
		JSONObject result = new JSONObject();
		result.put("count", spaceIds.size());
		result.put("message", "");
		result.put("result", "success");
		return result;
	}

	/**
	 * 统计 属于多建筑楼层的空间数据
	 *
	 * @param request
	 * @return
	 */
	@RequestMapping("/space-bd-fl-data")
	public AdmResponse querySpaceBdFlObj(HttpServletRequest request) {
		return spaceService.queryMultiBuildingOrFloorSpaces(request);
	}

	/**
	 * 查询没有和当前空间绑定的系统
	 *  description= "例如：prijectId=Pj4201050001,type=AirConditioningZone spaceId=Sp4201050001df2091cdf719443b80bb737aeabf0525 " + "spaceId 为当前空间id type为当前空间类型 "
	 * @param   type        空间类型  空间id确定，空间类型一定确定，此参数可以不用
	 * @param   spaceId     空间id
	 *
	 * @author lxy
	 */
	@RequestMapping("/unspace-in-sys")
	public AdmResponse unSpaceSys(@QueryParam("type") String type, @QueryParam("spaceId") String spaceId, @RequestBody AdmQueryCriteria request){
		request.setName(AdmSystem.OBJ_TYPE);
		// 设置关系条件
		request.resetRelationCond(true, "MechInArch", "Sy2Sp", spaceId, false);
		return systemService.query(request);
	}

	/**
	 * 查询没有和当前空间绑定的设备
	 * description ="例如：prijectId=Pj4201050001,type=AirConditioningZone spaceId=Sp4201050001df2091cdf719443b80bb737aeabf0525 " + "spaceId 为当前空间id type为当前空间类型 "
	 * @return
	 */
	@PostMapping("/unspace-in-eq")
	public AdmResponse unSpaceEq(@QueryParam("type") String type, @QueryParam("spaceId") String spaceId, @RequestBody AdmQueryCriteria request) {
		return queryEquipmentUnSpaceDirectly(type, spaceId, "MechInArch", request);
	}

	/**
	 * 查询没有服务于当前空间的设备
	 *  description ="例如：prijectId=Pj4201050001,type=AirConditioningZone spaceId=Sp4201050001df2091cdf719443b80bb737aeabf0525 " +
	 * 			"spaceId 为当前空间id type为当前空间类型
	 *
	 * @return
	 */
	@PostMapping("/unspace-for-eq")
	public AdmResponse unSpaceForEq(@QueryParam("type") String type, @QueryParam("spaceId") String spaceId, @RequestBody AdmQueryCriteria request) {
		return queryEquipmentUnSpaceDirectly(type, spaceId, "MechForArch", request);
	}
	/**
	 * 空间内没有服务于当前空间的设备
	 */
	@PostMapping("/unspace-for-eq-point")
	public AdmResponse unSpaceForEqPoint(@QueryParam("type") String type, @QueryParam("spaceId") String spaceId, @RequestBody AdmQueryCriteria request) {
		return queryEquipmentUnSpacePolygon(type, spaceId, "MechForArch", request);
	}

	/**
	 * 根据空间轮廓 计算设备的坐标是否在空间内
	 */
	@PostMapping("/unspace-fIn-eq-point")
	public AdmResponse unSpaceInEqPoint(@QueryParam("type") String type, @QueryParam("spaceId") String spaceId, @RequestBody AdmQueryCriteria request) {
		return queryEquipmentUnSpacePolygon(type, spaceId, "MechInArch", request);
	}

	/**
	 * 未关联业务空间的元空间  Sp2Si
	 */
	@PostMapping("/unspace-ispace")
	public AdmResponse unSpaceIspace(@QueryParam("objectType") String objectType, @RequestBody AdmDCSQueryRequest request) {
		//因现有floor没有轮廓线，先不做元空间和floor的轮廓的判断，使用关系查询
		request.setName(AdmISpace.OBJ_TYPE);
		// 设置关系条件
		AdmRelationTypeEnum typeEnum = AdmRelationTypeEnum.SP2SI;
		request.resetRelationCond(false, null, typeEnum.getRelCode(), objectType, null, false);
		request.addFilters("floorId = '"+request.getFloorId()+"'");
		AdmResponse responseIspace = ispaceService.doQuery(AdmContextUtil.toDmpContext(),request, AdmISpace.class);
		responseIspace.setFloorId(request.getFloorId());
		responseIspace.setZoneType(objectType);
		return responseIspace;
	}

	/**
	 * 查询未关联指定空间的设备
	 * @param type
	 * @param spaceId
	 * @param graphCode
	 * @param request
	 * @return
	 */
	private AdmResponse queryEquipmentUnSpaceDirectly(String type, String spaceId, String graphCode, AdmQueryCriteria request) {
		if (StrUtil.isBlank(spaceId)) {
			return AdmResponse.failure(ResponseCode.A0400.getDesc() + "空间id为空");
		}
		request.setName(AdmEquipment.OBJ_TYPE);
		// 设置关系条件
		request.resetRelationCond(true, graphCode, "Eq2Sp", type, spaceId, false);
		return equipmentService.doQuery(AdmContextUtil.toDmpContext(), request, AdmEquipment.class);
	}

	/**
	 * 查询未关联指定空间的设备，并且要在空间轮廓范围内
	 * @param type
	 * @param spaceId
	 * @param graphCode
	 * @param request
	 * @return
	 */
	private AdmResponse queryEquipmentUnSpacePolygon(String type, String spaceId, String graphCode, AdmQueryCriteria request) {
		if (StrUtil.isBlank(spaceId)) {
			return AdmResponse.failure(ResponseCode.A0400.getDesc() + "空间id为空");
		}
		InstanceUrlParam context = AdmContextUtil.toDmpContext();
		// 查询空间
		AdmQueryCriteria queryCriteria = new AdmQueryCriteria();
		queryCriteria.setName(AdmSpace.OBJ_TYPE);
		queryCriteria.addFilters("id = '"+spaceId+"'");
		AdmResponse spaceRes = spaceService.doQuery(context, queryCriteria, AdmSpace.class);
		if(spaceRes == null || CollUtil.isEmpty(spaceRes.getContent())) {
			return AdmResponse.failure(ResponseCode.A0400.getDesc() + "没有找到对应的空间");
		}
		AdmSpace admSpace = (AdmSpace) spaceRes.getContent().get(0);
		// 查询设备
		request.addFilters("not bimLocation isnull");
		request.setPageSize(Integer.MAX_VALUE);
		request.setName(AdmEquipment.OBJ_TYPE);
		// 设置关系条件
		request.resetRelationCond(true, graphCode, "Eq2Sp", type, spaceId, false);
		AdmResponse equipmentRes = equipmentService.doQuery(AdmContextUtil.toDmpContext(), request, AdmEquipment.class);
		if(equipmentRes == null || CollUtil.isEmpty(equipmentRes.getContent())) {
			return equipmentRes;
		}
		//根据空间轮廓和设备坐标过滤掉不在空间内的设备
		List<AdmEquipment> allEquipments = (List<AdmEquipment>) equipmentRes.getContent();
		List<AdmEquipment> filterEquipments = new ArrayList<>(16);
		ObjectMapper objectMapper = SpringHelper.getBean(ObjectMapper.class);
		ArrayNode jsonNodes = admSpace.getOutline();
		for(AdmEquipment equipment : allEquipments){
			String[] location = equipment.getBimLocation().split(",");
			ObjectNode bimLocation = objectMapper.createObjectNode()
					.put("x", location[0])
					.put("y", location[1]);
			if(location.length > 2){
				bimLocation.put("z", location[2]);
			}
			if(GeoToolsUtil.isPointInPoly(bimLocation, jsonNodes)){
				filterEquipments.add(equipment);
			}
		}
		equipmentRes.setContent(filterEquipments);
		equipmentRes.setTotal(Long.valueOf(CollUtil.size(filterEquipments)));
		return equipmentRes;
	}

	/*
	@PostMapping("/unspace-ispace")
	public AdmResponse unSpaceIspace(@QueryParam("objectType") String objectType, @RequestBody AdmDCSQueryRequest request) {
		// 查询楼层信息 需要楼层信息中的outline modelId
		AdmQueryCriteria admQueryCriteriaFl = new AdmQueryCriteria();
		admQueryCriteriaFl.setName(AdmFloor.OBJ_TYPE);
		admQueryCriteriaFl.setFilters(" id = '"+request.getFloorId()+"' ");
		AdmResponse responseFl = floorService.doQuery(AdmContextUtil.toDmpContext(), admQueryCriteriaFl, AdmFloor.class);
		if(CollUtil.isEmpty(responseFl.getContent())){
			return AdmResponse.failure("floorId 为空");
		}
		AdmFloor floor = (AdmFloor) responseFl.getContent().get(0);

		request.setName(AdmISpace.OBJ_TYPE);
		// 设置关系条件
        AdmRelationTypeEnum typeEnum = AdmRelationTypeEnum.SP2SI;
		request.resetRelationCond(false, null, typeEnum.getRelCode(), objectType, null, false);
		// 补充楼层条件
		if(StrUtil.isNotBlank(request.getFloorId())) {
            request.addFilters("bimId startwith '"+floor.getBimIdPre()+"' ");
		}
		AdmResponse responseIspace = ispaceService.doQuery(AdmContextUtil.toDmpContext(),request, AdmISpace.class);
		// 按照楼层轮廓线计算出不在轮廓线内的空间
		if(CollUtil.isNotEmpty(floor.getOutline())){
			// 计算ispace.outLine 在floor.outLine 内的ispace
			List<AdmISpace> iSpaceListTarget = new ArrayList<>(responseIspace.getTotal().intValue());
			List<AdmISpace> iSpaceList = (List<AdmISpace>) responseIspace.getContent();
			for(AdmISpace iSpace : iSpaceListTarget){
				if(CollUtil.isEmpty(iSpace.getOutline())){
					continue;
				}
				List<ObjectNode> ispaceOutLine = JSONArray.parseArray(iSpace.getOutline().toString(), ObjectNode.class);
//				if(GeoToolsUtil.isPolyInPoly(ispaceOutLine, floor.getOutline())){
//					iSpaceList.add(iSpace);
//				}
			}
			AdmResponse admResponse = AdmResponse.success(iSpaceList,request);
			admResponse.setFloorId(request.getFloorId());
			admResponse.setZoneType(objectType);
			admResponse.setTotal(responseIspace.getTotal());
			return admResponse;
		}else{
			responseIspace.setFloorId(request.getFloorId());
			responseIspace.setZoneType(objectType);
			return responseIspace;
		}
	}*/
}
