package de.soldin.gt2jump.test.gt2shapefile;

import java.io.File;
import java.net.URL;
import java.util.Iterator;

import com.vividsolutions.jump.feature.AttributeType;
import com.vividsolutions.jump.feature.BasicFeature;
import com.vividsolutions.jump.feature.Feature;
import com.vividsolutions.jump.feature.FeatureCollection;
import com.vividsolutions.jump.feature.FeatureDataset;
import com.vividsolutions.jump.feature.FeatureSchema;
import com.vividsolutions.jump.io.DriverProperties;
import com.vividsolutions.jump.io.IllegalParametersException;
import com.vividsolutions.jump.io.JUMPReader;
import com.vividsolutions.jump.io.JUMPWriter;
import com.vividsolutions.jump.io.datasource.StandardReaderWriterFileDataSource;

/**
 * @author ed
 *
 * ATTENTION: Writing and reading of FIDs is not currently implemented
 * as jump FIDs are integer and GT2's are string
 */
public class GT2ShapefileReaderWriter implements JUMPReader, JUMPWriter{

	/*
	 * @see com.vividsolutions.jump.io.JUMPReader#read(com.vividsolutions.jump.io.DriverProperties)
	 */
	public FeatureCollection read(DriverProperties dp) throws Exception {
		//FeatureCollection result = null;
		String shpfileName = dp.getProperty("File");
		if (shpfileName == null) {
			throw new IllegalParametersException("no File property specified");
		}

		URL url = new File(shpfileName).toURL();

		final org.geotools.data.DataSource gt2_datasource = new org.geotools.data.shapefile.ShapefileDataSource(url);
		org.geotools.feature.FeatureCollection gt2_features = gt2_datasource.getFeatures();

		return convert(gt2_features);
	}

	/*
	 * @see com.vividsolutions.jump.io.JUMPWriter#write(com.vividsolutions.jump.feature.FeatureCollection, com.vividsolutions.jump.io.DriverProperties)
	 */
	public void write(FeatureCollection featureCollection, DriverProperties dp) throws IllegalParametersException, Exception {
		String shpfileName = dp.getProperty("File");
		if (shpfileName == null) {
			throw new IllegalParametersException("no File property specified");
		}

		URL url = new File(shpfileName).toURL();

		final org.geotools.data.DataSource gt2_datasource = new org.geotools.data.shapefile.ShapefileDataSource(url);
		
		gt2_datasource.setFeatures(convert(featureCollection));
		
	}
	
	public org.geotools.feature.FeatureCollection convert(com.vividsolutions.jump.feature.FeatureCollection jump_features) throws Exception{
		// GT2 feature collection
		org.geotools.feature.FeatureCollection gt2_features = 
						org.geotools.feature.FeatureCollections.newCollection();
		
		for (Iterator iter = jump_features.iterator(); iter.hasNext();) {
			Feature jump_feature = (Feature) iter.next();
			
			// get jump_schema for feature
			FeatureSchema jump_fschema = jump_feature.getSchema();
			// create a feature schema for GT2
			org.geotools.feature.FeatureTypeFactory gt2_ftype_factory = org.geotools.feature.FeatureTypeFactory.newInstance(Integer.toString(jump_feature.getID()));
			// create an array of GT2 Attribs
			Object[] gt2_attribs = new Object[jump_fschema.getAttributeCount()];
			
			for (int i = 0; i<jump_fschema.getAttributeCount(); i++){
				
				// building schema
				AttributeType a_type = jump_fschema.getAttributeType(i);
				
				org.geotools.feature.AttributeType gt2_a_type = 
					org.geotools.feature.AttributeTypeFactory.newAttributeType(
													jump_fschema.getAttributeName(i),
													a_type.toJavaClass());
				gt2_ftype_factory.addType(gt2_a_type);
				
				// adding attrib
				gt2_attribs[i] = jump_feature.getAttribute(i);
						
			}
			
			//System.out.println(gt2_ftype_factory.toString());
			org.geotools.feature.FeatureType gt2_ftype = gt2_ftype_factory.getFeatureType();
			
			// create GT2 feature
			String fid = Integer.toString(jump_feature.getID());
			org.geotools.feature.Feature gt2_feature = gt2_ftype.create(gt2_attribs,fid);
			
			// add it to collection
			gt2_features.add(gt2_feature);
			
		}
		
		return gt2_features;
	}

	public com.vividsolutions.jump.feature.FeatureCollection convert(org.geotools.feature.FeatureCollection gt2_features){
		// jump feature collection
		FeatureCollection result = null;
		// a schema for the jump feature collection (what does jump need it for?) 
		FeatureSchema jump_fctype = null;
		
		for (Iterator iter = gt2_features.iterator(); iter.hasNext();) {
			org.geotools.feature.Feature gt2_feature = (org.geotools.feature.Feature) iter.next();
			
			// create jump_schema for feature
			FeatureSchema jump_fschema = new FeatureSchema();
			//jump_fschema.addAttribute("GEOMETRY", AttributeType.GEOMETRY);
			org.geotools.feature.FeatureType gt2_ftype = gt2_feature.getFeatureType();
			for (int i = 0; i<gt2_ftype.getAttributeCount(); i++){
				org.geotools.feature.AttributeType a_type = gt2_ftype.getAttributeType(i);
				// add to feature schema
				//System.out.println("<"+a_type.getName()+"("+a_type.getType().getName()+"):>");
				if (a_type.isGeometry())
					jump_fschema.addAttribute( a_type.getName(), AttributeType.GEOMETRY );
				else
					jump_fschema.addAttribute( a_type.getName(), AttributeType.toAttributeType( a_type.getType() ) );
			}
			//if (jump_fctype==null) jump_fctype = (FeatureSchema)jump_fschema.clone();
			
			
			// create jump_feature 
			Feature jump_feature = new BasicFeature(jump_fschema);
			Object[] gt2_attribs = gt2_feature.getAttributes(null);
			for (int i = 0; i < gt2_attribs.length; i++) {
				Object attrib = gt2_attribs[i];
				//System.out.print("<" + jump_fschema.getAttributeName(i)+"("+jump_fschema.getAttributeType(i)+"):"+attrib.toString() + ">");
				jump_feature.setAttribute(jump_fschema.getAttributeIndex(jump_fschema.getAttributeName(i)), attrib );
			}
			//System.out.println();
			
			// create feature_collection if not existing
			// ATTENTION: jump seems to handle only ONE consistent schema per collection
			if ( result == null ) result = new FeatureDataset(jump_fschema);
			result.add(jump_feature);
		
		}
		
		// never return null 
		if ( result == null ) result = new FeatureDataset(new FeatureSchema());
		gt2_features = null;
		System.gc();
		
		return result;	
	}

	public static class Shapefile extends StandardReaderWriterFileDataSource {
		public Shapefile() {
			super(new GT2ShapefileReaderWriter(), new GT2ShapefileReaderWriter(), new String[] { "shp" });
		}
	}
}




