
package test;

import java.awt.Color;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.util.Iterator;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.WindowConstants;

import org.geotools.data.coverage.grid.stream.StreamGridCoverageExchange;
import org.geotools.gui.swing.StyledMapPane;
import org.geotools.map.DefaultMapContext;
import org.geotools.map.MapContext;
import org.geotools.parameter.Parameter;
import org.geotools.referencing.FactoryFinder;
import org.geotools.renderer.j2d.RenderedMapScale;
import org.geotools.styling.ColorMap;
import org.geotools.styling.RasterSymbolizer;
import org.geotools.styling.Style;
import org.geotools.styling.StyleBuilder;
import org.opengis.coverage.grid.Format;
import org.opengis.coverage.grid.GridCoverage;
import org.opengis.coverage.grid.GridCoverageExchange;
import org.opengis.coverage.grid.GridCoverageReader;
import org.opengis.parameter.GeneralParameterValue;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CRSFactory;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.spatialschema.geometry.DirectPosition;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;

/**
 * Class to demonstrate use of ascii grid file.
 * 
 * @author achase
 */
public class MinimalTest {

    public void spearfishtest() throws Exception {
        long timeAtStart = System.currentTimeMillis();
        StyleBuilder sb = new StyleBuilder();
        
        GridCoverage gcDem = getSuperMontGrid();
        ColorMap cm = getBathyColorMap(sb);
        RasterSymbolizer rsDem = sb.createRasterSymbolizer(cm, 1);
        Style demStyle = sb.createStyle(rsDem);

        GridCoverage gcData = createGridCoverage("test.asc.gz");
        ColorMap cmData = getDataColorMap(sb);

        RasterSymbolizer rsData = sb.createRasterSymbolizer(cmData, .5);
        Style dataStyle = sb.createStyle(rsData);

        // Build the map
        MapContext map = new DefaultMapContext();

        map.addLayer(gcDem, demStyle);
        //
        map.addLayer(gcData, dataStyle);

        // Show the map
        StyledMapPane mapPane = new StyledMapPane();
        DirectPosition lowerCorner = gcDem.getEnvelope().getLowerCorner();
        DirectPosition upperCorner = gcDem.getEnvelope().getUpperCorner();
        Coordinate lowerCoord = new Coordinate(lowerCorner.getCoordinates()[0],
            lowerCorner.getCoordinates()[1]);
        Coordinate upperCoord = new Coordinate(upperCorner.getCoordinates()[0],
            upperCorner.getCoordinates()[1]);
        Envelope envelope = new Envelope(lowerCoord, upperCoord);
        map.setAreaOfInterest(envelope, gcDem.getCoordinateReferenceSystem());
        mapPane.setMapContext(map);
        mapPane.getRenderer().addLayer(new RenderedMapScale());

        JFrame frame = new JFrame();
        frame.setTitle("Test map");
        frame.setContentPane(mapPane.createScrollPane());
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setBounds(800, 200, 640, 480);
        frame.setVisible(true);
        long totalTime = System.currentTimeMillis() - timeAtStart;
        System.out.println("total time = " + totalTime);
//        long timeNow = System.currentTimeMillis();
//        while (System.currentTimeMillis() < (timeNow + 5000)) {
//            Thread.sleep(200);
//        }
//        frame.dispose();
//        gcDem = null;
//        gcData = null;
//        frame = null;
//        mapPane = null;
//        map = null;
//        System.gc();
    }

    private ColorMap getDataColorMap(StyleBuilder sb) {
        Color transparent = new Color(0.0f, 0.0f, 0.0f, 0.0f);
        ColorMap cm = sb.createColorMap(new String[]{"zero", "1-to-5",
            "5-to-10", "10-to-27", "28-to-infinity", "infinity"}, new double[]{
            0, 1, 5, 10, 27, 100}, new Color[]{transparent, Color.RED,
            Color.GREEN, Color.CYAN, Color.PINK, transparent},
            ColorMap.TYPE_INTERVALS);

        return cm;
    }
    
    private GridCoverage getSuperMontGrid() throws IllegalArgumentException, IOException{
        URL url = getClass().getResource("/grids/mont_super15/mont_super15.rrd");
        if (url == null) {
            throw new FileNotFoundException("Could not find specified grid.");
        }
        GridCoverageExchange gce = new StreamGridCoverageExchange();

        GridCoverageReader reader = gce.getReader(url);

        Format format = reader.getFormat();

        // get the parameters and set them
        ParameterValueGroup paramDescriptor = format.getReadParameters();
  
        paramDescriptor.parameter("Compressed").setValue(false);
        paramDescriptor.parameter("GRASS").setValue(false);
        format.getReadParameters().parameter("crs").setValue(getUtm10CRS());
        List paramList = paramDescriptor.values();
        GeneralParameterValue[] params = new GeneralParameterValue[paramList
            .size()];
        int i = 0;
        for (Iterator iter = paramList.iterator(); iter.hasNext(); i++) {
            Parameter param = (Parameter) iter.next();
            params[i] = param;
        }

        // read the grid
        System.out.println("Before grid coverage");
        long time = System.currentTimeMillis();
        GridCoverage gridCoverage = reader.read(params);
        System.out.println("time for grid coverage = " + (System.currentTimeMillis() - time));
        // just to be sure these big objects get garbage collected...
        reader = null;
        gce = null;
        format = null;
        return gridCoverage;
    }

    private GridCoverage createGridCoverage(String gridName)
        throws IllegalArgumentException, IOException {
        if (gridName == null) {
            throw new IllegalArgumentException(
                "gridName argument can not be null");
        }
        URL url = getClass().getResource("/grids/" + gridName);
        if (url == null) {
            throw new FileNotFoundException("Could not find specified grid.");
        }
        GridCoverageExchange gce = new StreamGridCoverageExchange();

        GridCoverageReader reader = gce.getReader(url);

        Format format = reader.getFormat();

        // get the parameters and set them
        ParameterValueGroup paramDescriptor = format.getReadParameters();
        boolean isCompressed = gridName.endsWith("gz");
        paramDescriptor.parameter("Compressed").setValue(isCompressed);
        paramDescriptor.parameter("GRASS").setValue(false);
        format.getReadParameters().parameter("crs").setValue(getUtm10CRS());
        List paramList = paramDescriptor.values();
        GeneralParameterValue[] params = new GeneralParameterValue[paramList
            .size()];
        int i = 0;
        for (Iterator iter = paramList.iterator(); iter.hasNext(); i++) {
            Parameter param = (Parameter) iter.next();
            params[i] = param;
        }

        // read the grid
        System.out.println("Before grid coverage");
        long time = System.currentTimeMillis();
        GridCoverage gridCoverage = reader.read(params);
        System.out.println("time for grid coverage = " + (System.currentTimeMillis() - time));
        // just to be sure these big objects get garbage collected...
        reader = null;
        gce = null;
        format = null;
        return gridCoverage;
    }

    private CoordinateReferenceSystem getUtm10CRS() {
        String wkt = "PROJCS[\"UTM_Zone_10N\", " + "GEOGCS[\"WGS84\", "
            + "DATUM[\"WGS84\", "
            + "SPHEROID[\"WGS84\", 6378137.0, 298.257223563]], "
            + "PRIMEM[\"Greenwich\", 0.0], "
            + "UNIT[\"degree\",0.017453292519943295], "
            + "AXIS[\"Longitude\",EAST], " + "AXIS[\"Latitude\",NORTH]], "
            + "PROJECTION[\"Transverse_Mercator\"], "
            + "PARAMETER[\"semi_major\", 6378137.0], "
            + "PARAMETER[\"semi_minor\", 6356752.314245179], "
            + "PARAMETER[\"central_meridian\", -123.0], "
            + "PARAMETER[\"latitude_of_origin\", 0.0], "
            + "PARAMETER[\"scale_factor\", 0.9996], "
            + "PARAMETER[\"false_easting\", 500000.0], "
            + "PARAMETER[\"false_northing\", 0.0], " + "UNIT[\"metre\",1.0], "
            + "AXIS[\"x\",EAST], " + "AXIS[\"y\",NORTH]]";

        CRSFactory csFactory = FactoryFinder.getCRSFactory(null);

        CoordinateReferenceSystem utm10 = null;
        try {
            utm10 = csFactory.createFromWKT(wkt);
        } catch (FactoryException e) {
            e.printStackTrace();
            System.exit(-1);
        }
        return utm10;

    }

    private ColorMap getBathyColorMap(StyleBuilder sb) {
        ColorMap cm = sb.createColorMap(new String[]{"fe", "fi", "fo", "crumb",
            "mum", "dumb", "stun", "above water", "above water"}, new double[]{-5000, -3000, -2800, -2500,
            -2000, -1000, 0, 1, 1000}, new Color[]{Color.BLUE.darker(), Color.BLUE,
            Color.CYAN, Color.GREEN, Color.YELLOW, Color.ORANGE, Color.RED, Color.BLACK, Color.BLACK},
            ColorMap.TYPE_RAMP);
        return cm;
    }

    public static void main(String[] args) {
        MinimalTest demo = new MinimalTest();
        try {
//            for (int i = 0; i < 10; i++) {
                demo.spearfishtest();
//            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
