package org.maptalks.gis.core.geojson.json;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.maptalks.gis.core.geojson.*;
import org.maptalks.gis.core.geojson.ext.Circle;
import org.maptalks.gis.core.geojson.ext.Ellipse;
import org.maptalks.gis.core.geojson.ext.Rectangle;
import org.maptalks.gis.core.geojson.ext.Sector;

import java.util.HashMap;
import java.util.Map;

public class GeoJSONFactory {
    static Map<String, Class> geoJsonTypeMap = new HashMap<String, Class>();

    static {
        geoJsonTypeMap.put(GeoJsonTypes.TYPE_POINT,Point.class);
        geoJsonTypeMap.put(GeoJsonTypes.TYPE_LINESTRING,LineString.class);
        geoJsonTypeMap.put(GeoJsonTypes.TYPE_POLYGON,Polygon.class);
        geoJsonTypeMap.put(GeoJsonTypes.TYPE_MULTIPOINT,MultiPoint.class);
        geoJsonTypeMap.put(GeoJsonTypes.TYPE_MULTILINESTRING,MultiLineString.class);
        geoJsonTypeMap.put(GeoJsonTypes.TYPE_MULTIPOLYGON,MultiPolygon.class);
        geoJsonTypeMap.put(GeoJsonTypes.TYPE_GEOMETRYCOLLECTION,GeometryCollection.class);
        //extended geojson types
        geoJsonTypeMap.put(GeoJsonTypes.TYPE_EXT_CIRCLE,Circle.class);
        geoJsonTypeMap.put(GeoJsonTypes.TYPE_EXT_ELLIPSE,Ellipse.class);
        geoJsonTypeMap.put(GeoJsonTypes.TYPE_EXT_RECTANGLE,Rectangle.class);
        geoJsonTypeMap.put(GeoJsonTypes.TYPE_EXT_SECTOR,Sector.class);
    }

    public static GeoJSON create(String json) {
        JSONObject node = JSON.parseObject(json);
        return create(node);
    }

    /**
     * 将json解析为Feature数组
     * @param json
     * @return
     */
    public static Feature[] createFeatureArray(String json) {
        JSONArray node = JSON.parseArray(json);

        int size = node.size();
        Feature[] result = new Feature[size];
        for (int i = 0; i < size; i++) {
            GeoJSON geojson = create(((JSONObject) node.get(i)));
           if (geojson instanceof Geometry) {
                result[i] = new Feature(((Geometry) geojson));
            } else {
               result[i] = ((Feature) geojson);
           }
        }
        return result;
    }

    /**
     * 将json解析为Geometry数组
     * @param json
     * @return
     */
    public static Geometry[] createGeometryArray(String json) {
        JSONArray node = JSON.parseArray(json);

        int size = node.size();
        Geometry[] result = new Geometry[size];
        for (int i = 0; i < size; i++) {
            GeoJSON geojson = create(((JSONObject) node.get(i)));
            if (geojson instanceof Feature) {
                result[i] = ((Feature) geojson).getGeometry();
            } else {
                result[i] = ((Geometry) geojson);
            }
        }
        return result;
    }

    private static GeoJSON create(JSONObject node) {
        String type = node.getString("type");
        if ("FeatureCollection".equals(type)) {
            return readFeatureCollection(node);
        } else if ("Feature".equals(type)) {
            return readFeature(node);
        } else {
            return readGeometry(node, type);
        }
    }
    
    private static FeatureCollection readFeatureCollection(JSONObject node) {

        JSONArray jFeatures = node.getJSONArray("features");
        JSONObject crsJson = node.getJSONObject("crs");
        CRS crs = null;
        if (crsJson != null) {
            crs = JSON.toJavaObject(crsJson, CRS.class);
        }
        if (jFeatures == null) {
            //return a empty FeatureCollection
            FeatureCollection result = new FeatureCollection();
            result.setCrs(crs);
            result.setFeatures(new Feature[0]);
            return result;
        }
        int size = jFeatures.size();
        Feature[] features = new Feature[size];
        for (int i=0;i<size;i++) {
            features[i] = readFeature(jFeatures.getJSONObject(i));
        }
        FeatureCollection result = new FeatureCollection();
        result.setCrs(crs);
        result.setFeatures(features);
        return result;
    }
    
    private static Feature readFeature(JSONObject node) {
        JSONObject geoJ = node.getJSONObject("geometry");
        Geometry geo = null;
        if (geoJ != null) {
            geo = readGeometry(geoJ, geoJ.getString("type"));
        }
        node.remove("geometry");
        Feature result = JSON.toJavaObject(node, Feature.class);
        result.setGeometry(geo);
        return result;
    }
    
    private static Geometry readGeometry(JSONObject node, String type) {
        if (GeoJsonTypes.TYPE_GEOMETRYCOLLECTION.equals(type)) {
            JSONObject crsJson = node.getJSONObject("crs");
            CRS crs = null;
            if (crsJson != null) {
                crs = JSON.toJavaObject(crsJson, CRS.class);
            }
            GeometryCollection result = new GeometryCollection(new Geometry[0]);
            result.setCrs(crs);
            JSONArray jGeos = node.getJSONArray("geometries");
            if (jGeos != null) {
                int size = jGeos.size();
                Geometry[] geometries = new Geometry[size];
                for (int i=0;i<size;i++) {
                    JSONObject jgeo = jGeos.getJSONObject(i);
                    geometries[i] = readGeometry(jgeo, jgeo.getString("type"));
                }
                result.setGeometries(geometries);
            } else {
                //return a empty GeometryCollection
                result.setGeometries(new Geometry[0]);
            }
            return result;
        }
        Class clazz = getGeoJsonType(type);
        Object obj = JSON.toJavaObject(node, clazz);
        return ((Geometry) obj);
    }

    public static Class getGeoJsonType(String type) {
        Class clazz = geoJsonTypeMap.get(type);
        return clazz;
    }
}

@@ -1559,32 +1559,508 @@
 e(node);%0A    %7D%0A%0A
+    /**%0A     * %E5%B0%86json%E8%A7%A3%E6%9E%90%E4%B8%BAFeatureCollection%E6%95%B0%E7%BB%84%0A     * @param json%0A     * @return%0A     */%0A    public static FeatureCollection%5B%5D createFeatureCollectionArray(String json) %7B%0A        JSONArray node = JSON.parseArray(json);%0A        int size = node.size();%0A        FeatureCollection%5B%5D result = new FeatureCollection%5Bsize%5D;%0A        for (int i = 0; i %3C size; i++) %7B%0A            result%5Bi%5D = ((FeatureCollection) create(((JSONObject) node.get(i))));%0A        %7D%0A        return result;%0A    %7D%0A%0A
     /**%0A     * %E5%B0%86
@@ -2220,33 +2220,32 @@
 rseArray(json);%0A
-%0A
         int size
@@ -2416,32 +2416,33 @@
 )));%0A           
+ 
 if (geojson inst
@@ -2551,32 +2551,33 @@
 %0A               
+ 
 result%5Bi%5D = ((Fe
@@ -2585,32 +2585,33 @@
 ture) geojson);%0A
+ 
            %7D%0A   
@@ -2639,32 +2639,33 @@
  result;%0A    %7D%0A%0A
+%0A
     /**%0A     * %E5%B0%86

add method: createFeatureArrayCollection