import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.geom.impl.CoordinateArraySequence;

import fr.ocelet.runtime.List;

/**
 * Holds a list of SPolygon. One SPolygon has one shell and maybe one or more
 * holes .
 * 
 * @author pdegenne@teledetection.fr
 * @since 22 mars 2013
 */
public class MPolygon {

	private List<SPolygon> listOfPolys;

	/**
	 * This constructor is kept for backward compatibility It creates one
	 * SPolygon with shell and no hole for every List<Position>
	 * 
	 * @param llp
	 */
	public MPolygon(final List<List<Position>> llp) {
		super();
		this.listOfPolys = new List<SPolygon>();
		for (List<Position> sh : llp) {
			listOfPolys.add(new SPolygon(sh));
		}
	}

	public MPolygon() {
		super();
		listOfPolys = new List<SPolygon>();
	}

	/**
	 * Adds one line to a MPolygon. Kept for backward compatibility. The line
	 * parameter will be transformed into one SPolygon with no hole.
	 * 
	 * @param line
	 * @deprecated Use addSPolygon() instead
	 */
	public void addPolygon(List<Position> line) {
		addSPolygon(new SPolygon(line));
	}

	/**
	 * Adds one SPolygon to this MPolygon
	 * @param sp The SPolygon to be added
	 */
	public void addSPolygon(SPolygon sp) {
		listOfPolys.add(sp);
	}
	
	/**
	 * Helper to translate this MPolygon using one same service call
	 * 
	 * @param dx
	 *            Distance to be applied to x
	 * @param dy
	 *            Distance to be applied to y
	 * @since 4 jun 2012
	 */
	public void addTo_xy(double dx, double dy) {
		for (SPolygon sp : listOfPolys) {
			sp.addTo_xy(dx, dy);
		}
	}

	/**
	 * Gives the number of SPolygons contained in this MPolygon. Kept for
	 * backward compatibility.
	 * 
	 * @deprecated Use nbPolys instead.
	 * @return An int number
	 */
	public int nbLines() {
		return nbPolys();
	}

	/**
	 * Gives the number of polys in this MPolygon
	 * 
	 * @return An int number
	 * @since 23 mars 2013
	 */
	public int nbPolys() {
		return listOfPolys.size();
	}

	/**
	 * Returns one polygon from this MPolygon
	 * 
	 * @deprecated Use getSHell() or getPoly() instead
	 * @param index
	 *            Number of the required polygon
	 * @return One Line in the form of a List<Position>
	 */
	public List<Position> getPolygon(int index) {
		return getShell(index);
	}

	/**
	 * Returns the content of the shell for the SPolygon pointed by the
	 * specified index
	 * 
	 * @return A List of Position
	 */
	public List<Position> getShell(int index) {
		return getSPolygon(index).getShell();
	}

	/**
	 * Returns one SPolygon from this MPolygon
	 * 
	 * @param index
	 * @return On SPolygon pointed by the given index.
	 */
	public SPolygon getSPolygon(int index) {
		return listOfPolys.get(index);
	}

	/**
	 * Produces a JTS Geometry object from the content of this MPolygon
	 * 
	 * @return Either a Polygon or a MultiPolygon depending on the number of
	 *         geometry elements contained in the MPolygon
	 */
	public Geometry asGeometry() {
		int sz = listOfPolys.size();
		Geometry geom = null;
		if (sz == 1) {
			geom = listOfPolys.get(0).asGeometry();
		} else if (sz > 1) {
			Polygon[] polys = new Polygon[sz];
			for (int i = 0; i < sz; i++) {
				polys[i] = (Polygon) listOfPolys.get(i).asGeometry();
			}
			geom = new MultiPolygon(polys, new GeometryFactory());
		}
		return geom;
	}

	/**
	 * @return The Position that is the centroid of this MPolygon
	 */
	public Position getCentroid() {
		Point centroid = this.asGeometry().getCentroid();
		return new Position(centroid.getX(), centroid.getY());
	}

}
