package org.gcube.application.geoportal.common.model.document.filesets.sdi;

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.bson.Document;
import org.gcube.application.geoportal.common.model.document.filesets.Materialization;

import java.util.List;

public class GCubeSDILayer extends Materialization {

    @Data
    @NoArgsConstructor
    /**
     *    A GeoJSON object MAY have a member named "bbox" to include
     *    information on the coordinate range for its Geometries, Features, or
     *    FeatureCollections.  The value of the bbox member MUST be an array of
     *    length 2*n where n is the number of dimensions represented in the
     *    contained geometries, with all axes of the most southwesterly point
     *    followed by all axes of the more northeasterly point.  The axes order
     *    of a bbox follows the axes order of geometries.
     *
     *    source https://datatracker.ietf.org/doc/html/rfc7946#section-5
     */
    public static class BBOX extends Document {

        public final String asGeoJSONBBox(){
            StringBuilder builder = new StringBuilder("[");
            builder.append(getMaxX()+","); // W
            builder.append(getMinY()+","); // S
            if(is3d()) builder.append(getMinZ()+","); // Z

            builder.append(getMinX()+","); // E
            builder.append(getMaxY()+","); // N
            if(is3d()) builder.append(getMaxZ()+","); // Z


            builder.deleteCharAt(builder.length());
            builder.append("]");
            return builder.toString();
        }
        public double[] asGeoJSONArray(){
            if(is3d()){
                return new double[]{getMaxX(),getMinY(),getMinZ(),getMinX(),getMaxY(),getMaxZ()};
            }else return new double[]{getMaxX(),getMinY(),getMinX(),getMaxY()};
        }

        public static final BBOX fromGeoJSON(double[] coords){
            BBOX toReturn = new BBOX();
            toReturn.setMaxX(coords[0]);
            toReturn.setMinY(coords[1]);

            if(coords.length == 6){
                // 3D
                toReturn.setMinZ(coords[2]);
                toReturn.setMinX(coords[3]);
                toReturn.setMaxY(coords[4]);
                toReturn.setMaxZ(coords[5]);
            }else {
                toReturn.setMinX(coords[2]);
                toReturn.setMaxY(coords[3]);
            }
            return toReturn;
        }

        public static final BBOX WORLD=new BBOX(180d,-180d,90d,-90d);

        public static final BBOX WORLD_3D=new BBOX(180d,-180d,90d,-90d);

        public static final String MAX_X="_maxX";
        public static final String MAX_Y="_maxY";
        public static final String MAX_Z="_maxZ";
        public static final String MIN_X="_minX";
        public static final String MIN_Y="_minY";
        public static final String MIN_Z="_minZ";


        public BBOX(Double maxX,Double minX,Double maxY,Double minY,Double maxZ,Double minZ){
            this(maxX,minX,maxY,minY);
            setMaxZ(maxZ);
            setMinZ(minZ);
        }
        public BBOX(Double maxX,Double minX,Double maxY,Double minY){
            setMaxX(maxX);
            setMinX(minX);
            setMaxY(maxY);
            setMinY(minY);
        }

        @JsonIgnore
        public BBOX setMaxX(Double d){this.put(MAX_X,d);return this;}
        @JsonIgnore
        public BBOX setMaxY(Double d){this.put(MAX_Y,d);return this;}
        @JsonIgnore
        public BBOX setMaxZ(Double d){this.put(MAX_Z,d);return this;}
        @JsonIgnore
        public BBOX setMinX(Double d){this.put(MIN_X,d);return this;}
        @JsonIgnore
        public BBOX setMinY(Double d){this.put(MIN_Y,d);return this;}
        @JsonIgnore
        public BBOX setMinZ(Double d){this.put(MIN_Z,d);return this;}
        @JsonIgnore
        public Double getMinY(){return (Double) this.getOrDefault(MIN_Y,-90d);}
        @JsonIgnore
        public Double getMaxY(){return (Double) this.getOrDefault(MAX_Y,90d);}
        @JsonIgnore
        public Double getMinX(){return (Double) this.getOrDefault(MIN_X,-180d);}
        @JsonIgnore
        public Double getMaxX(){return (Double) this.getOrDefault(MAX_X,180d);}
        @JsonIgnore
        public Double getMinZ(){return (Double) this.getOrDefault(MIN_Z,null);}
        @JsonIgnore
        public Double getMaxZ(){return (Double) this.getOrDefault(MAX_Z,null);}

        @JsonIgnore
        public Boolean is3d(){
            return getMinZ()!=null && getMaxZ() !=null;
        }
    }


    public static final String GCUBE_SDY_LAYER_TYPE="gcube-sdi-layer";
    public static final String OGC_LINKS="_ogcLinks";
    public static final String B_BOX = "_bbox";
    public static final String PLATFORM_INFO="_platformInfo";

    public GCubeSDILayer(){
        super(GCUBE_SDY_LAYER_TYPE);
    }

    @JsonIgnore
    public List getOGCLinks(){return this.get(OGC_LINKS, List.class);}
    @JsonIgnore
    public Object getBBox(){return this.get(B_BOX);}
    @JsonIgnore
    public List getPlatformInfo(){return this.get(PLATFORM_INFO,List.class);}

    
}
