import java.awt.Color;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.visitor.UniqueVisitor;
import org.geotools.styling.PolygonSymbolizer;
import org.geotools.styling.SLDTransformer;
import org.geotools.styling.Style;
import org.geotools.styling.StyleBuilder;
import org.opengis.filter.FilterFactory2;
import org.opengis.filter.expression.Expression;
import org.opengis.filter.expression.Function;

public class StyleGeneratorNaturalEarth {

    public static void main(String[] args) throws Exception {
        // grab all the names from the shapefile
        String filePath = "/home/aaime/devel/gisData/naturalEarth/10m_cultural/10m_admin_1_states_provinces_shp.shp";
        ShapefileDataStore shp = new ShapefileDataStore(new File(filePath).toURI().toURL());
        SimpleFeatureCollection features = shp.getFeatureSource().getFeatures();
        UniqueVisitor visitor = new UniqueVisitor("OBJECTID");
        features.accepts(visitor, null);
        List<String> names = new ArrayList<String>(visitor.getUnique());
        Collections.sort(names);
        shp.dispose();
        
        // names
        System.out.println(names);
        System.out.println(names.size());
        
        // build the recode function 
        FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(null);
        Expression[] table = new Expression[names.size() * 2 + 1];
        table[0] = ff.property("OBJECTID");
        Set<Color> colors = new HashSet<Color>();
        for (int i = 0; i < names.size(); i++) {
            table[i * 2 + 1] = ff.literal(names.get(i));
            table[i * 2 + 2] = ff.literal(uniqueDarkColor(colors));
        }
        Function recode = ff.function("recode", table);
        
        // build the line style
        StyleBuilder sb = new StyleBuilder();
        PolygonSymbolizer ps = sb.createPolygonSymbolizer();
        ps.getFill().setColor(recode);
        ps.getStroke().setWidth(ff.literal(0.3));
        
        Style style = sb.createStyle(ps);
        
        // write out the sld
        SLDTransformer tx = new SLDTransformer();
        tx.setIndentation(2);
        File target = new File("/tmp/provicens.sld");
        tx.transform(style, new FileOutputStream(target));
    }

    private static Color uniqueDarkColor(Set<Color> colors) {
        for(int i = 0; i < 100; i++) {
            int red = (int) Math.round(Math.random() * 255);
            int green = (int) Math.round(Math.random() * 255);
            int blue = (int) Math.round(Math.random() * 255);
            Color c = new Color(red, green, blue);
            if(!colors.contains(c)) {
                colors.add(c);
                return c;
            }
        }
        throw new RuntimeException("Could not find a unique color after 100 iterations");
    }
}
