package com.skyversation.poiaddr.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.skyversation.poiaddr.addquery.AddressQueryEngine;
import com.skyversation.poiaddr.addquery.Constant;
import com.skyversation.poiaddr.bean.AddressResult;
import com.skyversation.poiaddr.bean.GeoJsonBean;
import com.skyversation.poiaddr.entity.SjArrDzbzhSjWcbryDzxx;
import com.skyversation.poiaddr.service.impl.SjArrDzbzhSjWcbryDzxxServiceImpl;
import com.skyversation.poiaddr.util.status.AddressLevel;
import org.geotools.geojson.geom.GeometryJSON;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.MultiPolygon;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKTReader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

@Service
public class AreaService {

    @Resource
    private SjArrDzbzhSjWcbryDzxxServiceImpl sjArrDzbzhSjWcbryDzxxService;

    private static AreaService instance;

    public static AreaService getInstance() {
        if (instance == null) {
            return new AreaService();
        }
        return instance;
    }

    @Value("${app.area}")
    private String area;

    @Value("${app.town}")
    private String town;

    WKTReader reader = new WKTReader(JTSFactoryFinder.getGeometryFactory());
    public List<GeoJsonBean> shAllAdministrativeDivisionPolygonList = new ArrayList<>();
    public List<GeoJsonBean> shAllToensPolygonList = new ArrayList<>();

    @PostConstruct
    public void initGeoData() {
        System.out.println("<<<<<<<<------AreaService>initGeoData------>>>>>>>>>");
        instance = this;
        Thread thread3 = new Thread(this::initPolygons);
        thread3.start();

        try {
            thread3.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
//      TODO 初始化配置文件变量
        Constant.setTowns(town.split("、"));
        Constant.setArea(area);
        System.out.println("<<<<<<<<------根据配置文件为AREA赋值:" + Constant.getArea());
        System.out.println("<<<<<<<<------当前AMAP_CITY_CODE:" + Constant.getAMAP_CITY_CODE());
//      TODO 网络连通性测试，可以请求一下测试的市中心地址
        try {
            System.out.println("电脑最大线程数：" + Runtime.getRuntime().availableProcessors());
            System.out.println("<<<<<<<<------开始网络连通性测试");
            long startTime = System.currentTimeMillis();
            List<String> addrs = new ArrayList<>();
            addrs.add("上海市松江区乐都路339号");
            AddressResult addressResult = AddressQueryEngine.getInstance().commonSearchByName(addrs);
            long endTime = System.currentTimeMillis();
            System.out.println(">>>>>>>>------网络连通性测试完成！用时" + (endTime - startTime) / 1000 + "秒！结果:" + addressResult);
        } catch (Exception e) {
            System.err.println(">>>>>>>>------网络连通性测试结果:" + e);
        }
//      TODO 数据库连通性测试
        try {
            System.out.println("<<<<<<<<------开始数据库连通性测试");
            List<SjArrDzbzhSjWcbryDzxx> listData = sjArrDzbzhSjWcbryDzxxService.getAllDataPage(1);
            System.out.println(">>>>>>>>------数据库连通性测试结果:" + listData.toString());
        } catch (Exception e) {
            System.err.println(">>>>>>>>------数据库连通性测试结果:" + e);
        }
    }

    public void initPolygons() {
        List<List<GeoJsonBean>> lis = new ArrayList<>();
        lis.add(shAllAdministrativeDivisionPolygonList);
        lis.add(shAllToensPolygonList);
        String[] path = new String[]{"geojson/sh_all_administrative_division.geojson", "geojson/sh_all_towns.geojson"};

        for (int j = 0; j < path.length; j++) {
            BufferedReader reader = null;
            try {
                // 创建 ClassPathResource 对象，指定静态文件的路径
                ClassPathResource resource = new ClassPathResource(path[j]);
                // 获取文件的输入流
                reader = new BufferedReader(new InputStreamReader(resource.getInputStream()));
                String line;
                StringBuilder sb = new StringBuilder();
                while ((line = reader.readLine()) != null) {
                    sb.append(line).append("\r\n");
                }
                reader.close();
                JSONObject json = JSONObject.parseObject(sb.toString());

                JSONArray featrues = json.getJSONArray("features");

                for (int i = 0; i < featrues.size(); i++) {
                    JSONObject properties = featrues.getJSONObject(i).getJSONObject("properties");
                    JSONObject geoJson = new JSONObject();
                    geoJson.put("type", "MultiPolygon");
                    geoJson.put("coordinates",
                            featrues.getJSONObject(i).getJSONObject("geometry").getJSONArray("coordinates"));
                    GeometryJSON geometryJSON = new GeometryJSON();
                    MultiPolygon multiPolygon = geometryJSON.readMultiPolygon(geoJson.toJSONString());
                    GeoJsonBean geoJsonBean = new GeoJsonBean();
                    geoJsonBean.setProperties(properties);
                    geoJsonBean.setMultiPolygon(multiPolygon);
                    lis.get(j).add(geoJsonBean);
                }
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("<<<<<<<<------run geo data error------>>>>>>>>>");
            }
        }

        System.out.println("<<<<<<<<------run geo data complete------>>>>>>>>>");
    }

    public GeoJsonBean isInadPolygon(double lon, double lat) {
        try {
            Geometry point = reader.read("POINT (" + lat + " " + lon + ")");
            for (GeoJsonBean bean : shAllAdministrativeDivisionPolygonList) {
                if (bean.getMultiPolygon().contains(point)) {
                    return bean;
                }
            }
            return null;
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    public GeoJsonBean isInTownPolygon(double lon, double lat) {
        try {
            Geometry point = reader.read("POINT (" + lat + " " + lon + ")");
            for (GeoJsonBean bean : shAllToensPolygonList) {
                if (bean.getMultiPolygon().contains(point)) {
                    return bean;
                }
            }
            return null;
        } catch (ParseException e) {
            throw new RuntimeException(e);

        }
    }
}
