package com.fdkankan.dxf.parse.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fdkankan.dxf.fdjson.vo.FdFloors;
import com.fdkankan.dxf.fdjson.vo.FdFloorsPanJson;
import com.fdkankan.dxf.fdjson.vo.FdPoints;
import com.fdkankan.dxf.fdjson.vo.FdWalls;
import com.fdkankan.dxf.generate.DxfDocWriter;
import com.fdkankan.dxf.generate.DxfGenSupport;
import com.fdkankan.dxf.generate.Vector3;
import com.fdkankan.dxf.generate.enums.LineWidthEnum;
import com.fdkankan.dxf.generate.model.DxfArc;
import com.fdkankan.dxf.generate.model.DxfLine;
import com.fdkankan.dxf.generate.model.DxfLwPolyLine;
import com.fdkankan.dxf.generate.model.base.Color;
import com.fdkankan.dxf.generate.model.base.DxfEntity;
import com.fdkankan.dxf.generate.model.support.DxfExtent;
import com.fdkankan.dxf.math.MathArcUtil;
import com.fdkankan.dxf.parse.ParseDXF;
import com.fdkankan.dxf.parse.model.entities.GeometricLine;
import com.fdkankan.dxf.parse.resolver.DxfResolver;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

public class FdJsonToDxfUtil {

    /**
     * floorplan_user.json 转 dxf
     * @param fdJsonPath floorplan.json 路径
     * @param dxfPath   dxf生成路径
     * @param subgroup  多楼层，楼层数 floorplan中需存在
     */
    public static void fdJsonToDxf(String fdJsonPath,String dxfPath,Integer subgroup)  {
        try {
            DxfDocWriter dxfDocWriter = new DxfDocWriter();
            String msg = new String(Files.readAllBytes(Paths.get(fdJsonPath)));
            JSONObject jsonObject = JSONObject.parseObject(msg);
            JSONArray floors = jsonObject.getJSONArray("floors");
            for (Object obj : floors) {
                JSONObject floor = (JSONObject) (obj);
                if(floor.getInteger("subgroup") != null && floor.getInteger("subgroup").equals(subgroup)){
                    plantWall(dxfPath,dxfDocWriter,floor);
                }
            }
            dxfDocWriter.save(dxfPath, true);
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    /**
     * floorplan_user.json 转 dxf
     * @param fdJsonPath floorplan_user.json 路径
     * @param dxfPath   dxf生成路径
     */
    public static void fdJsonToDxf(String fdJsonPath,String dxfPath)  {
        try {
            DxfDocWriter dxfDocWriter = new DxfDocWriter();

            String msg = new String(Files.readAllBytes(Paths.get(fdJsonPath)));
            JSONObject jsonObject = JSONObject.parseObject(msg);
            JSONArray floors = jsonObject.getJSONArray("floors");
            for (Object obj : floors) {
                JSONObject floor = (JSONObject) (obj);
                plantWall(dxfPath,dxfDocWriter,floor);
                plantSymbols(dxfPath,dxfDocWriter,floor);
                planFurnitures(dxfPath,dxfDocWriter,floor);
            }
            dxfDocWriter.save(dxfPath, true);
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    /**
     * 墙，根据起始点画线
     */
    private static void plantWall(String filePath, DxfDocWriter dxfDocWriter,JSONObject fools) {
        HashMap<String, FdPoints> wallMap= new HashMap<>();

        JSONObject walls = fools.getJSONObject("walls");
        JSONObject points = fools.getJSONObject("points");
        for (String key : points.keySet()) {
            JSONObject obj = points.getJSONObject(key);
            FdPoints point = new FdPoints(obj.getDouble("x") * 100, obj.getDouble("y") * 100);
            wallMap.put(key,point);
        }

        for (String key : walls.keySet()) {
            JSONObject wall = walls.getJSONObject(key);
            String start = wall.getString("start");
            String end = wall.getString("end");
            Boolean out = wall.getBoolean("out");
            drawLinePoint(filePath,wallMap.get(start),wallMap.get(end),dxfDocWriter,out);
        }

    }
    /**
     * 门，根据起始点画线
     */
    private static void plantSymbols(String filePath,DxfDocWriter dxfDocWriter, JSONObject fools) {
        JSONObject symbols = fools.getJSONObject("symbols");
        for (String key : symbols.keySet()) {
            JSONArray points2d = symbols.getJSONObject(key).getJSONArray("points2d");
            String openSide = symbols.getJSONObject(key).getString("openSide");
            drawDoor(points2d, openSide.equals("LEFT"),dxfDocWriter);
        }
    }

    private static void planFurnitures(String filePath,DxfDocWriter dxfDocWriter, JSONObject fools) {
        JSONObject furnitures = fools.getJSONObject("furnitures");
        for (String key : furnitures.keySet()) {
            JSONObject obj = furnitures.getJSONObject(key);
            String furnKey = obj.getString("geoType");
            JSONObject center = obj.getJSONObject("center");

            Double x = center.getDouble("x") * 100;
            Double y = center.getDouble("y") * 100;
        }

    }


    public static void drawLinePoint(String filePath,FdPoints point,FdPoints point2,DxfDocWriter dxfDocWriter,Boolean out){
        DxfLine dxfLine = new DxfLine();
        dxfLine.setStartPoint(new Vector3(point.getX(), point.getY(), 0));
        dxfLine.setEndPoint(new Vector3(point2.getX(), point2.getY(), 0));
        dxfLine.setColor(new Color(0, 180, 64));
        if(out){
            dxfLine.setColor(new Color(0, 255, 0));
        }
        dxfDocWriter.addEntity(dxfLine);
    }

    public static void drawLinePoint(Vector3 point,Vector3 point2,DxfDocWriter dxfDocWriter){
        DxfLine dxfLine = new DxfLine();
        dxfLine.setStartPoint(new Vector3(point.getX(), point.getY(), 0));
        dxfLine.setEndPoint(new Vector3(point2.getX(), point2.getY(), 0));
        dxfLine.setColor(new Color(0, 120, 32));
        dxfDocWriter.addEntity(dxfLine);
    }

    public static void drawArc(Vector3 point,Vector3 point2,DxfDocWriter dxfDocWriter,Boolean isLeft){
        DxfArc dxfArc = new DxfArc();
        dxfArc.setCenter(point);
        dxfArc.setColor(Color.green);
        //勾股定理
        Double a = Math.abs(point.getX() - point2.getX()) * Math.abs(point.getX() - point2.getX());
        Double b = Math.abs(point.getY() - point2.getY()) * Math.abs(point.getY() - point2.getY());
        dxfArc.setRadius(Math.sqrt(a + b));
        //角度
        Double atan = Math.atan((point2.getY()-point.getY()) / (point2.getX()-point.getX())) / 3.14 * 180;
        dxfArc.setStartAngle(atan);
        dxfArc.setEndAngle(atan + 90);
        if(isLeft){
            dxfArc.setStartAngle(atan + 90);
            dxfArc.setEndAngle(-(180 - atan));
        }
        dxfDocWriter.addEntity(dxfArc);
    }

    public static void drawDoor(JSONArray points2d,Boolean isLeft,DxfDocWriter dxfDocWriter){
        List<Vector3> vector3List  = new ArrayList<>();
        for (Object object : points2d) {
            JSONObject jso = (JSONObject) object;
            vector3List.add( new Vector3(jso.getDouble("x") * 100,jso.getDouble("y") * 100,jso.getDouble("z")==null?0:jso.getDouble("z") * 100));
        }
        drawLinePoint(vector3List.get(0),vector3List.get(3),dxfDocWriter);
        drawArc(vector3List.get(0),vector3List.get(3),dxfDocWriter,isLeft);
    }


    /**
     * dxf 转 floorplan_user.json
     * @param dxfPath   dxf生成路径
     * @param jsonPath floorplan_user.json 路径
     */
    public static String dxfToFdJson(String dxfPath,String jsonPath){
        try {
            FdFloorsPanJson fdFloorsPanJson = new FdFloorsPanJson();
            FdFloors fdFloors = new FdFloors();
            JSONObject walls = fdFloors.getWalls();
            JSONObject points = fdFloors.getPoints();
            fdFloorsPanJson.getFloors().add(fdFloors);

            DxfResolver build = ParseDXF.build(dxfPath);
            List<GeometricLine> geometricLineList = build.getGeometricLineList();
            writeFdLine(geometricLineList,points,walls);
            String jsonString = JSONObject.toJSONString(fdFloorsPanJson);
            WriteStringToFile.writeFile(jsonString,jsonPath);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return null;
    }

    private static void writeFdLine(List<GeometricLine> geometricLineList,JSONObject points,JSONObject walls) {
        HashSet<String> pointSet = new HashSet<>();
        HashMap<String,String> pointMap = new HashMap<>();
        for (GeometricLine geometricLine : geometricLineList) {
            pointSet.add(geometricLine.getStartX() + "," + geometricLine.getStartY());
            pointSet.add(geometricLine.getEndX() + "," + geometricLine.getEndY());
        }
        int pointIndex = 0;
        for (String xy : pointSet) {
            FdPoints fdPoints = new FdPoints();
            fdPoints.setX(Double.valueOf(xy.split(",")[0])/100);
            fdPoints.setY(Double.valueOf(xy.split(",")[1])/100);
            points.put("point"+pointIndex,fdPoints);
            pointMap.put(xy,"point"+pointIndex);
            pointIndex ++;
        }
        Integer wallIndex = 0;
        for (GeometricLine geometricLine : geometricLineList) {
            FdWalls fdWalls = new FdWalls();
            String pointNameStart = pointMap.get(geometricLine.getStartX() + "," + geometricLine.getStartY());
            String pointNameEnd = pointMap.get(geometricLine.getEndX() + "," + geometricLine.getEndY());
            fdWalls.setStart(pointNameStart);
            fdWalls.setEnd(pointNameEnd);
            walls.put("wall"+wallIndex,fdWalls);
            wallIndex ++;
        }
    }

    public static void main(String[] args) {
        String inPath ="D:\\cad\\work\\111\\1.json";
        String outPath ="D:\\cad\\work\\111\\1.dxf";
        FdJsonToDxfUtil.fdJsonToDxf(inPath,outPath);
    }
}
