class ProjectionHandler {

    public List<ReferencedEnvelope> getQueryEnvelopes()
            throws TransformException, FactoryException {
        CoordinateReferenceSystem renderingCRS = renderingEnvelope.getCoordinateReferenceSystem();
        if(renderingCRS instanceof GeographicCRS && !CRS.equalsIgnoreMetadata(renderingCRS, WGS84)) {
            // special case, if we just transform the coordinates are going to be wrapped by the referencing
            // subsystem directly
            ReferencedEnvelope re = renderingEnvelope;
            List<ReferencedEnvelope> envelopes = new ArrayList<ReferencedEnvelope>();
            envelopes.add(re);

            if(CRS.getAxisOrder(renderingCRS) == CRS.AxisOrder.NORTH_EAST) {
                if (re.getMinY() >= -180.0 && re.getMaxY() <= 180) {
                    return Collections
                            .singletonList(transformEnvelope(renderingEnvelope, sourceCRS));
                }
                
                // We need to split reprojected envelope and normalize it. To be lenient with
                // situations in which the data is just broken (people saying 4326 just because they
                // have no idea at all) we don't actually split, but add elements
                if (re.getMinY() < -180) {
                    envelopes.add(new ReferencedEnvelope(re.getMinY() + 360, 180, re.getMinX(), re
                            .getMaxX(), re.getCoordinateReferenceSystem()));
                }
                if (re.getMaxY() > 180) {
                    envelopes.add(new ReferencedEnvelope(-180, re.getMaxY() - 360, re.getMinX(), re
                            .getMaxX(), re.getCoordinateReferenceSystem()));
                }
                
            } else {
                if (re.getMinX() >= -180.0 && re.getMaxX() <= 180) {
                    return Collections
                            .singletonList(transformEnvelope(renderingEnvelope, sourceCRS));
                }
            
                // We need to split reprojected envelope and normalize it. To be lenient with
                // situations in which the data is just broken (people saying 4326 just because they
                // have no idea at all) we don't actually split, but add elements
                
                if (re.getMinX() < -180) {
                    envelopes.add(new ReferencedEnvelope(re.getMinX() + 360, 180, re.getMinY(), re
                            .getMaxY(), re.getCoordinateReferenceSystem()));
                }
                if (re.getMaxX() > 180) {
                    envelopes.add(new ReferencedEnvelope(-180, re.getMaxX() - 360, re.getMinY(), re
                            .getMaxY(), re.getCoordinateReferenceSystem()));
                }
            }
    
            mergeEnvelopes(envelopes);
            reprojectEnvelopes(sourceCRS, envelopes);
    
            return envelopes;
            
            
        } else {
            if (!Double.isNaN(datelineX) && renderingEnvelope.getMinX() < datelineX
                    && renderingEnvelope.getMaxX() > datelineX
                    && renderingEnvelope.getWidth() < radius) {
                double minX = renderingEnvelope.getMinX();
                double minY = renderingEnvelope.getMinY();
                double maxX = renderingEnvelope.getMaxX();
                double maxY = renderingEnvelope.getMaxY();
                ReferencedEnvelope re1 = new ReferencedEnvelope(minX, datelineX - EPS, minY,
                        maxY, renderingCRS);
                ReferencedEnvelope tx1 = transformEnvelope(re1, WGS84);
                tx1.expandToInclude(180, tx1.getMinY());
                ReferencedEnvelope re2 = new ReferencedEnvelope(datelineX + EPS, maxX, minY,
                        maxY, renderingCRS);
                ReferencedEnvelope tx2 = transformEnvelope(re2, WGS84);
                if (tx2.getMinX() > 180) {
                    tx2.translate(-360, 0);
                }
                tx2.expandToInclude(-180, tx1.getMinY());
                List<ReferencedEnvelope> result = new ArrayList<ReferencedEnvelope>();
                result.add(tx1);
                result.add(tx2);
                mergeEnvelopes(result);
                return result;
            } else {
                return getSourceEnvelopes(renderingEnvelope);
            }
        }
    }

    public  ProjectionHandler(CoordinateReferenceSystem sourceCRS, Envelope validAreaBounds, ReferencedEnvelope renderingEnvelope);
    public  ProjectionHandler(CoordinateReferenceSystem sourceCRS, Geometry validArea, ReferencedEnvelope renderingEnvelope);

}