package com.ruoyi.ibs.grid.util;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.io.WKTWriter;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@Slf4j
public class GeoJsonFileToWktConverter {

    private static final GeometryFactory geometryFactory = new GeometryFactory();
    private static final ObjectMapper objectMapper = new ObjectMapper();
    private static final WKTWriter wktWriter = new WKTWriter();

    public static String convertFile(String filePath) throws IOException {
        File file = new File(filePath);
        if (!file.exists()) {
            log.error("文件不存在: " + filePath);
            return null;
        }
        JsonNode rootNode = objectMapper.readTree(file);
        if (rootNode.has("type")) {
            String type = rootNode.get("type").asText();
            if ("FeatureCollection".equals(type)) {
                JsonNode features = rootNode.get("features");
                for (JsonNode feature : features) {
                    return convertFeature(feature);
                }
            } else if ("Feature".equals(type)) {
                return convertFeature(rootNode);
            } else {
                // Assume it's a geometry
                Geometry geometry = parseGeometry(rootNode);
                return wktWriter.write(geometry);
            }
        }
        return null;
    }

    public static Geometry convertGeometry(String filePath) throws IOException {
        File file = new File(filePath);
        JsonNode rootNode = objectMapper.readTree(file);
        if (rootNode.has("type")) {
            String type = rootNode.get("type").asText();
            if ("FeatureCollection".equals(type)) {
                JsonNode features = rootNode.get("features");
                for (JsonNode feature : features) {
                    JsonNode geometry = feature.get("geometry");
                    Geometry jtsGeometry = parseGeometry(geometry);
                    return jtsGeometry;

                }
            } else if ("Feature".equals(type)) {
                JsonNode geometry = rootNode.get("geometry");
                Geometry jtsGeometry = parseGeometry(geometry);
                return jtsGeometry;
            } else {
                // Assume it's a geometry
                Geometry geometry = parseGeometry(rootNode);
                return geometry;
            }
        }
        return null;
    }

    private static String convertFeature(JsonNode feature) {
        JsonNode geometry = feature.get("geometry");
        Geometry jtsGeometry = parseGeometry(geometry);
        return wktWriter.write(jtsGeometry);
    }

    private static Geometry parseGeometry(JsonNode node) {
        String type = node.get("type").asText();
        JsonNode coordinatesNode = node.get("coordinates");

        switch (type) {
            case "Point":
                return parsePoint(coordinatesNode);
            case "LineString":
                return parseLineString(coordinatesNode);
            case "Polygon":
                return parsePolygon(coordinatesNode);
            case "MultiPoint":
                return parseMultiPoint(coordinatesNode);
            case "MultiLineString":
                return parseMultiLineString(coordinatesNode);
            case "MultiPolygon":
                return parseMultiPolygon(coordinatesNode);
            default:
                throw new IllegalArgumentException("Unsupported geometry type: " + type);
        }
    }

    private static Point parsePoint(JsonNode coordinates) {
        double x = coordinates.get(0).asDouble();
        double y = coordinates.get(1).asDouble();
        return geometryFactory.createPoint(new Coordinate(x, y));
    }

    private static LineString parseLineString(JsonNode coordinates) {
        Coordinate[] coords = parseCoordinates(coordinates);
        return geometryFactory.createLineString(coords);
    }

    private static Polygon parsePolygon(JsonNode coordinates) {
        LinearRing shell = geometryFactory.createLinearRing(parseCoordinates(coordinates.get(0)));
        LinearRing[] holes = new LinearRing[coordinates.size() - 1];
        for (int i = 1; i < coordinates.size(); i++) {
            holes[i - 1] = geometryFactory.createLinearRing(parseCoordinates(coordinates.get(i)));
        }
        return geometryFactory.createPolygon(shell, holes);
    }

    private static MultiPoint parseMultiPoint(JsonNode coordinates) {
        Point[] points = new Point[coordinates.size()];
        for (int i = 0; i < coordinates.size(); i++) {
            points[i] = parsePoint(coordinates.get(i));
        }
        return geometryFactory.createMultiPoint(points);
    }

    private static MultiLineString parseMultiLineString(JsonNode coordinates) {
        LineString[] lineStrings = new LineString[coordinates.size()];
        for (int i = 0; i < coordinates.size(); i++) {
            lineStrings[i] = parseLineString(coordinates.get(i));
        }
        return geometryFactory.createMultiLineString(lineStrings);
    }

    private static MultiPolygon parseMultiPolygon(JsonNode coordinates) {
        Polygon[] polygons = new Polygon[coordinates.size()];
        for (int i = 0; i < coordinates.size(); i++) {
            polygons[i] = parsePolygon(coordinates.get(i));
        }
        return geometryFactory.createMultiPolygon(polygons);
    }

    private static Coordinate[] parseCoordinates(JsonNode coordinates) {
        List<Coordinate> coords = new ArrayList<>();
        for (JsonNode coord : coordinates) {
            double x = coord.get(0).asDouble();
            double y = coord.get(1).asDouble();
            coords.add(new Coordinate(x, y));
        }
        return coords.toArray(new Coordinate[0]);
    }

    public static void main(String[] args) {
        String filePath = "D:\\数字支行\\地图api\\经纬度解析\\浙江省_low\\嘉兴市.json";
        try {
            String wktResults = convertFile(filePath);
            System.out.println(wktResults);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
