package com.fdkankan.model.utils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fdkankan.common.util.FileUtils;
import com.fdkankan.model.bean.*;

import java.awt.geom.Point2D;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

public class FloorPlanUserUtil {

	public static void main(String[] args) {
		JSONObject floorPlanUserJson = FloorPlanUserUtil.createFloorPlanUserJson("D:\\Downloads\\floorplan_cad(3).json");
		FileUtil.writeUtf8String(floorPlanUserJson.toJSONString(), "D:\\Downloads\\demo.json");

	}

	/**
	 * 根据floorplan_cad.json文件生成houseType.json
	 * @param filePath
	 * @return
	 */
	public static JSONObject createFloorPlanUserJson(String filePath) {

		JSONArray floors = readFloorJson(filePath);
		if(CollUtil.isEmpty(floors)){
			return null;
		}

		JSONObject house = new JSONObject();
		house.put("unit", "m");
		house.put("angle", 0);
		house.put("type", "cad");
		house.put("version", "v4.0");

		JSONArray targetFloors = new JSONArray();
		house.put("floors", targetFloors);

		int currentId = 0;

		for(int i = 0; i < floors.size(); i++){
			JSONObject floor = (JSONObject)floors.get(i);
			Map<String, Object> result = createFloorHandler(floor, currentId);
			JSONArray points = (JSONArray)result.get("pointArr");
			JSONArray walls = (JSONArray)result.get("wallArr");
			JSONArray symbols = (JSONArray)result.get("symbols");
			currentId = (int)result.get("currentId");
			JSONObject targetFloor = new JSONObject();
			targetFloor.put("points", convertArrToMap(points));
			targetFloor.put("walls", convertArrToMap(walls));
			targetFloor.put("symbols", convertArrToMap(symbols));
			targetFloor.put("id", floor.getInteger("id"));
			targetFloor.put("name",floor.getString("name"));
			targetFloor.put("subgroup", floor.getInteger("subgroup"));
			targetFloors.add(targetFloor);
		}

		house.put("currentId", currentId);

		return house;
	}


	private static Map<String, JSONObject> convertArrToMap(JSONArray arr){
		Map<String, JSONObject> result = new HashMap<>();
		if(CollUtil.isEmpty(arr)){
			return result;
		}

		arr.stream().forEach(item->{
			JSONObject object = (JSONObject)item;
			String vectorId = object.getString("vectorId");
			result.put(vectorId, object);
		});

		return result;
	}

	private static Map<String, Object> createFloorHandler(JSONObject floor, int currentId){

		Map<String, Object> result = new HashMap<>();
		//处理点
		Map<Integer, VertexBean> vertexMap = new HashMap<>();
		Map<String, PointBean> pointMap = new HashMap<>();
		Map<Integer, String> vpMap = new HashMap<>();
		JSONArray vertexArr = floor.getJSONArray("vertex-xy");
		if(CollUtil.isNotEmpty(vertexArr)){
			for(int i = 0; i < vertexArr.size(); i++){
				Object o = vertexArr.get(i);

				VertexBean vertexBean = JSON.parseObject(JSON.toJSONString(o), VertexBean.class);
				Integer vertexId = vertexBean.getId();
				vertexMap.put(vertexId, vertexBean);

				String pointId = "Point" + currentId;
				pointMap.put(pointId, PointBean.builder().geoType("Point").vectorId(pointId).x(vertexBean.getX()).y(vertexBean.getY()).build());
				++currentId;

				vpMap.put(vertexId, pointId);
			}
		}

		//处理墙
		Map<Integer, SegmentBean> segmentMap = new HashMap<>();
		Map<String, WallBean> wallMap = new HashMap<>();
		Map<Integer, String> swMap = new HashMap<>();
		JSONArray segmentArr = floor.getJSONArray("segment");
		Map<String, String> startMap = new HashMap<>();
		Map<String, String> endMap = new HashMap<>();
		if(CollUtil.isNotEmpty(segmentArr)){
			for(int i = 0; i < segmentArr.size(); i++){
				Object o = segmentArr.get(i);

				SegmentBean segmentBean = JSON.parseObject(JSON.toJSONString(o), SegmentBean.class);
				String startPointId = vpMap.get(segmentBean.getA());
				String endPointId = vpMap.get(segmentBean.getB());
				segmentBean.setStartPointId(startPointId);
				segmentBean.setEndPointId(endPointId);

				Integer segmentId = segmentBean.getId();
				segmentMap.put(segmentId, segmentBean);

				String wallId = "Wall" + currentId;
				WallBean wallBean = WallBean.builder()
						.geoType("Wall")
						.vectorId(wallId)
						.start(segmentBean.getStartPointId())
						.end(segmentBean.getEndPointId())
						.children(new HashSet<>())
						.width(0.2d)
						.build();
				wallMap.put(wallId, wallBean);
				++currentId;

				startMap.put(wallBean.getStart(), wallBean.getVectorId());
				endMap.put(wallBean.getEnd(), wallBean.getVectorId());

				swMap.put(segmentId, wallId);
			}
		}

		//处理门窗
		Map<String, SymbolBean> symbolMap = new HashMap<>();
		JSONArray shapesArr = floor.getJSONArray("shapes");
		if(CollUtil.isNotEmpty(shapesArr)){
			List<JSONObject> windowAndDoors = shapesArr.stream().filter(v->{
				JSONObject obj = (JSONObject) v;
				String category = obj.getString("category");
				if(StrUtil.isNotEmpty(category) && (category.contains("Window") || category.contains("Door"))){
					return true;
				}
				return false;
			}).map(v->(JSONObject)v).collect(Collectors.toList());
			if(CollUtil.isNotEmpty(windowAndDoors)){
				for (int i = 0; i < windowAndDoors.size(); i++){

					JSONObject jsonObject = windowAndDoors.get(i);
					String category = jsonObject.getString("category");
					String geoType = null;
					String name = null;
					String openSide = null;
					if(category.contains("Window")){
						geoType = category;
						name = jsonObject.getString("name");
						openSide = "RIGHT";
					}
					if(category.contains("Door")){
						geoType = "SingleDoor";
						name = "单开门";
						openSide = "LEFT";
					}

					//vectorId
					String symbolId = geoType + currentId;

					JSONObject line = jsonObject.getJSONObject("line");
					String openSideAi = line.getString("openSide");
					if(StrUtil.isNotEmpty(openSideAi)){
						if("L".equals(openSideAi)){
							openSide = "LEFT";
						}
						if("R".equals(openSideAi)){
							openSide = "RIGHT";
						}
					}
					JSONObject point0 = line.getJSONObject("point_0");
					Integer segmentId0 = point0.getInteger("segment_id");
					point0.remove("segment_id");

					JSONObject point1 = line.getJSONObject("point_1");
					Integer segmentId1 = point1.getInteger("segment_id");
					point1.remove("segment_id");

					//求两点之间的距离
					Point2D p0 = new Point2D.Double(point0.getDouble("x"), point0.getDouble("y"));
					Point2D p1 = new Point2D.Double(point1.getDouble("x"), point1.getDouble("y"));
					double distance = p0.distance(p1);

					//设置墙的children
					String wall0 = swMap.get(segmentId0);
					String wall1 = swMap.get(segmentId1);
					WallBean wallBean0 = wallMap.get(wall0);
					wallBean0.getChildren().add(symbolId);
					WallBean wallBean1 = wallMap.get(wall1);
					wallBean1.getChildren().add(symbolId);

					SymbolBean symbolBean = SymbolBean.builder().name(name).geoType(geoType)
							.vectorId(symbolId).openSide(openSide).startPoint(point0).endPoint(point1).len(distance)
							.parent(wall0).build();
					symbolMap.put(symbolId, symbolBean);

					++currentId;
				}
			}
		}


		Collection<PointBean> pointBeans = pointMap.values();
		for (PointBean pointBean : pointBeans) {
			Map<String, String> parent = new HashMap<>();
			String startParent = startMap.get(pointBean.getVectorId());
			String endParent = endMap.get(pointBean.getVectorId());
			if(StrUtil.isNotEmpty(startParent)){
				parent.put(startParent, "start");
			}
			if(StrUtil.isNotEmpty(endParent)){
				parent.put(endParent, "end");
			}
			pointBean.setParent(parent);
		}
		JSONArray pointArr = JSON.parseArray(JSON.toJSONString(pointBeans));
		result.put("pointArr", pointArr);

		Collection<WallBean> wallBeans = wallMap.values();
		JSONArray wallArr = JSON.parseArray(JSON.toJSONString(wallBeans));
		result.put("wallArr", wallArr);

		if(CollUtil.isNotEmpty(symbolMap)){
			JSONArray symbolArr = JSON.parseArray(JSON.toJSONString(symbolMap.values()));
			result.put("symbols", symbolArr);
		}

		result.put("currentId", currentId);

		return result;

	}


	private static JSONArray readFloorJson(String filePath) {
		try {
			JSONObject floorplan = FileUtils.readJson(filePath);
			JSONArray floors = floorplan.getJSONArray("floors");
			return floors;
		} catch (IOException e) {

			return null;
		}
	}

}








