import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;

import de.micromata.opengis.kml.v_2_2_0.Coordinate;
import de.micromata.opengis.kml.v_2_2_0.Document;
import de.micromata.opengis.kml.v_2_2_0.Feature;
import de.micromata.opengis.kml.v_2_2_0.Folder;
import de.micromata.opengis.kml.v_2_2_0.Kml;
import de.micromata.opengis.kml.v_2_2_0.LineString;
import de.micromata.opengis.kml.v_2_2_0.Placemark;
import de.micromata.opengis.kml.v_2_2_0.Point;
import de.micromata.opengis.kml.v_2_2_0.Polygon;
import fr.ocelet.runtime.List;

public class KmlFile {

	String name;
	List<List<List<Double>>> coordinatesList = new List<List<List<Double>>>();
	HashMap<String,List<List<List<Double>>>> coordsMap = new HashMap<String,List<List<List<Double>>>>();
	HashMap<String,List<de.micromata.opengis.kml.v_2_2_0.Geometry>> geomMap = 
		new HashMap<String, List<de.micromata.opengis.kml.v_2_2_0.Geometry>>();
	
@Deprecated
public void createLineString(String name,String fileName,List<List<Double>> coordList){
		
	    this.name = name;
	    Kml kml = new Kml();
	    Document doc = kml.createAndSetDocument().withName(name).withOpen(true);

		 // create a Folder
	    Folder folder = doc.createAndAddFolder();
	    
		Placemark placemark = folder.createAndAddPlacemark();
		LineString ls = placemark.createAndSetLineString();		
		
		java.util.List<Coordinate> coordinates = ls.createAndSetCoordinates();
		
		for(List<Double> coords : coordList){
			
			Coordinate coordinate = new Coordinate(coords.get(0), coords.get(1));
			coordinates.add(coordinates.size(), coordinate);
		}
		
		  try {
			  File file = new File(fileName);
				kml.marshal(file);
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	}

@Deprecated
public void createLineString(String name,String fileName){
	
    this.name = name;
    Kml kml = new Kml();
    Document doc = kml.createAndSetDocument().withName(name).withOpen(true);

	 // create a Folder
    Folder folder = doc.createAndAddFolder();
    
    for(List<List<Double>> coordList : coordinatesList){
    	
    	Placemark placemark = folder.createAndAddPlacemark();
    	LineString ls = placemark.createAndSetLineString();		
    	
    	java.util.List<Coordinate> coordinates = ls.createAndSetCoordinates();
    	
    	for(List<Double> coords : coordList){
    		
    		Coordinate coordinate = new Coordinate(coords.get(0), coords.get(1));
    		coordinates.add(coordinates.size(), coordinate);
    	}
    }
	
	
	  try {
		  File file = new File(fileName);
			kml.marshal(file);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
}

public void createGoogleFile(String fileName){
	
	Kml kml = new Kml();
	Document doc = kml.createAndSetDocument().withName(name).withOpen(true);	
	for(String i : geomMap.keySet()){
	
		Folder newFolder = doc.createAndAddFolder();
		newFolder.withName(i).createAndSetTimeSpan().withBegin(i + "-01-01").withEnd(i + "-12-31");	
		
		for(de.micromata.opengis.kml.v_2_2_0.Geometry coords : geomMap.get(i)){			
		
			Placemark placemark = newFolder.createAndAddPlacemark();			
			
	    	LineString ls = placemark.createAndSetLineString();	
	    	placemark.addToPlacemarkObjectExtension(coords);
	    	/*java.util.List<Coordinate> coordinates = ls.getCoordinates();
	    	
			for(int j=0;j<coords.size();j++){
				
				Coordinate coordinate = new Coordinate(coords.get(j).get(0), coords.get(j).get(1));
				coordinates.add(coordinate);				
			}	*/
		}				
	}
	 try {
		  File file = new File(fileName);
			kml.marshal(file);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
}

public void createKmlFile(String fileName){	
		
	Kml kml = new Kml();
	Document doc = kml.createAndSetDocument().withName(name).withOpen(true);	
	for(String i : coordsMap.keySet()){
	
		Folder newFolder = doc.createAndAddFolder();
		newFolder.withName(i).createAndSetTimeSpan().withBegin(i + "-01-01").withEnd(i + "-12-31");	
		
		for(List<List<Double>> coords : coordsMap.get(i)){			
		
			Placemark placemark = newFolder.createAndAddPlacemark();			
			
	    	LineString ls = placemark.createAndSetLineString();	
	    	java.util.List<Coordinate> coordinates = ls.getCoordinates();
	    	
			for(int j=0;j<coords.size();j++){
				
				Coordinate coordinate = new Coordinate(coords.get(j).get(0), coords.get(j).get(1));
				coordinates.add(coordinate);				
			}	
		}				
	}
	 try {
		  File file = new File(fileName);
			kml.marshal(file);
			System.out.println("fichier kml crée dans :"+file.getAbsolutePath());
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
}

@Deprecated
	public void addLine(String lineName,String fileName, List<List<Double>> coordList){
	
		Kml unmarshal = Kml.unmarshal(new File(fileName));
		Document doc = (Document) unmarshal.getFeature();
		try {
			String s = fileName.substring(0, fileName.length()-4)+".kmz";
			s = fileName;
			// File file = new File(s);
			unmarshal.marshalAsKmz(s);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		/*Folder oldFolder = (Folder) doc.getFeature().get(0);
		//Folder folder = new Folder();//(Folder) document.getFeature().get(0);
		// Folder folder = doc.createAndAddFolder();
			//Placemark placemark = ((Placemark) oldFolder.getFeature().get(0)).clone();
			//Folder newFolder = new Folder();
			//newFolder.addToFeature(placemark);
			Placemark placemark = oldFolder.createAndAddPlacemark();
		LineString ls = placemark.createAndSetLineString();				
		java.util.List<Coordinate> coordinates = ls.createAndSetCoordinates();
		
		for(List<Double> coords : coordList){
			
			Coordinate coordinate = new Coordinate(coords.get(0), coords.get(1));
			coordinates.add(coordinates.size(), coordinate);
		}
		Document newDocument = new Document().withName(lineName);
		newDocument.getFeature().add(oldFolder);
		unmarshal.setFeature(newDocument);
		
		try {
			String s = fileName.substring(0, fileName.length()-4)+".kmz";
			s = fileName;
			// File file = new File(s);
			unmarshal.marshalAsKmz(s);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}*/
	}
	
	public void addCoordinateStep(String date,List<List<Double>> coordinates){
		
		if(coordsMap.get(date) == null){
			coordsMap.put(date, new List<List<List<Double>>>());
		}
		
		coordsMap.get(date).add(coordinates);
	}
	
	public void addLineStringStep(String date,List<List<Double>> coordinates){
		LineString lineString = new LineString();
		for(List<Double> coordinate : coordinates){
			Coordinate coord = new Coordinate(coordinate.get(0), coordinate.get(1));
			lineString.getCoordinates().add(coord);
		}
		if(geomMap.get(date) == null){
			geomMap.put(date, new List<de.micromata.opengis.kml.v_2_2_0.Geometry>());
		}		
		
		geomMap.get(date).add(lineString);		
	}
	
	public void addPolygonStep(String date,List<List<Double>> coordinates){
		Polygon polygon = new Polygon();
		for(List<Double> coordinate : coordinates){
			Coordinate coord = new Coordinate(coordinate.get(0), coordinate.get(1));
			polygon.getOuterBoundaryIs().getLinearRing().getCoordinates().add(coord);
			
		}
		if(geomMap.get(date) == null){
			geomMap.put(date, new List<de.micromata.opengis.kml.v_2_2_0.Geometry>());
		}		
		
		geomMap.get(date).add(polygon);		
	}
	
	public void addPointStep(String date,List<Double> coordinate){
		
		Point point = new Point();
		
			point.addToCoordinates(coordinate.get(0), coordinate.get(1));
		
		if(geomMap.get(date) == null){
			geomMap.put(date, new List<de.micromata.opengis.kml.v_2_2_0.Geometry>());
		}		
		
		geomMap.get(date).add(point);		
	}
	
	public void addCoordinates(List<List<Double>> coordinate){
		coordinatesList.add(coordinate);
	}
	
	
	public void resetCoordinates(){
		coordinatesList = new List<List<List<Double>>>();
	}
	public void iterate(String fileName,List<String> dates){
		
		
		Kml unmarshal = Kml.unmarshal(new File(fileName));
		Document document = (Document) unmarshal.getFeature();
		
		Folder oldFolder = (Folder) document.getFeature().get(0);
		Folder folder = new Folder();	
		Folder newFolder = new Folder();
		newFolder.withName(dates.get(0)).createAndSetTimeSpan().withBegin(dates.get(0) + "-01-01").withEnd(dates.get(0) + "-12-31");

		for(Feature feature : oldFolder.getFeature()){
			Placemark placemark = (Placemark) feature.clone();
			newFolder.addToFeature(placemark);
			
		}
		folder.addToFeature(newFolder);
		//int index = 0;
		
		for(String i : coordsMap.keySet()){
			/*if(i==0){
				
			}else{*/
					
			newFolder = new Folder();
			//Placemark placemark = ((Placemark) ((Folder)folder.getFeature().get(index)).getFeature().get(0)).clone();
			//String current = iterator.next();		
				    	
			//newFolder.withName(dates.get(i)).createAndSetTimeSpan().withBegin(dates.get(i) + "-01-01").withEnd(dates.get(i) + "-12-31");		
			newFolder.withName(i).createAndSetTimeSpan().withBegin(i + "-01-01").withEnd(i + "-12-31");		
			for(List<List<Double>> coords : coordsMap.get(i)){
				
				Placemark placemark = newFolder.createAndAddPlacemark();
				
				newFolder.addToFeature(placemark);
		    	LineString ls = placemark.createAndSetLineString();	
		    	java.util.List<Coordinate> coordinates = ls.getCoordinates();
				for(int j=0;j<coords.size();j++){
					Coordinate coordinate = new Coordinate(coords.get(j).get(0), coords.get(j).get(1));
					coordinates.add(coordinate);
					
				}	
			}
			//}
						
			//index++;
			folder.addToFeature(newFolder);		
		}
		
		Document newDocument = new Document().withName(name);
		newDocument.getFeature().add(folder);
		unmarshal.setFeature(newDocument);
		
		try {
			String s = fileName.substring(0, fileName.length()-4)+".kmz";
			s = fileName;
			// File file = new File(s);
			unmarshal.marshalAsKmz(s);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/*@Deprecated
	public void iterateAndMoveLine(String fileName,List<String> dates,Double alpha,Double beta,Double k){
		
		Iterator<String> iterator = dates.iterator();
		Kml unmarshal = Kml.unmarshal(new File(fileName));
		Document document = (Document) unmarshal.getFeature();
		
		Folder oldFolder = (Folder) document.getFeature().get(0);
		Folder folder = new Folder();			
		
		Placemark placemark = ((Placemark) oldFolder.getFeature().get(0)).clone();
		Folder newFolder = new Folder();
		newFolder.addToFeature(placemark);
		folder.addToFeature(newFolder);
		
		newFolder.withName(dates.get(0)).createAndSetTimeSpan().withBegin(dates.get(0) + "-01-01").withEnd(dates.get(0) + "-12-31");
		
		dates.remove(0);
		iterator = dates.iterator();
		int index =0;
		while (iterator.hasNext()) {
			
			newFolder = new Folder();
			placemark = ((Placemark) ((Folder)folder.getFeature().get(index)).getFeature().get(0)).clone();
			String current = iterator.next();
			
			newFolder.withName(current).createAndSetTimeSpan().withBegin(current + "-01-01").withEnd(current + "-12-31");				
						
			newFolder.addToFeature(placemark);
			LineString ls = (LineString)placemark.getGeometry();
			java.util.List<Coordinate> coordinates = ls.getCoordinates();
			List<List<Double>> coords = new List<List<Double>>();
			for(Coordinate c : coordinates){
				List<Double> latLong = new List<Double>();
				latLong.add(c.getLatitude());
				latLong.add(c.getLongitude());
				coords.add(latLong);
			}
			coords = getMoovedCoordinates(coords, alpha, beta, k);
			coordinates.removeAll(coordinates);
			for(int i=0;i<coords.size();i++){
				Coordinate coordinate = new Coordinate(coords.get(i).get(0), coords.get(i).get(1));
				coordinates.add(coordinate);
				
			}						
			index++;
			folder.addToFeature(newFolder);			
			
		}
		Document newDocument = new Document().withName(name);
		newDocument.getFeature().add(folder);
		unmarshal.setFeature(newDocument);
		
		try {
			String s = fileName.substring(0, fileName.length()-4)+".kmz";
			s = fileName;
			// File file = new File(s);
			unmarshal.marshalAsKmz(s);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}*/
	
	@Deprecated
	public void iterate(String fileName,List<String> noms, Integer size, List<List<Double>> coordList){
	
		
		Iterator<String> iterator = noms.iterator();
		Kml unmarshal = Kml.unmarshal(new File(fileName));
		Document document = (Document) unmarshal.getFeature();
		Folder oldFolder = (Folder) document.getFeature().get(0);
		Folder folder = new Folder();

		folder.setName("Test");
		int i = 0;
		Placemark placemark = ((Placemark) oldFolder.getFeature().get(0)).clone();
		Folder newFolder = new Folder();
		newFolder.addToFeature(placemark);
		folder.addToFeature(newFolder);
		newFolder.withName("2007").createAndSetTimeSpan().withBegin("2007" + "-01-01").withEnd("2007" + "-12-31");
		while (iterator.hasNext()) {
			
			newFolder = new Folder();
			placemark = ((Placemark) ((Folder)folder.getFeature().get(i)).getFeature().get(0)).clone();
			String current = iterator.next();
			
			newFolder.withName(current).createAndSetTimeSpan().withBegin(current + "-01-01").withEnd(current + "-12-31");				
						
			newFolder.addToFeature(placemark);
			LineString ls = (LineString)placemark.getGeometry();
			java.util.List<Coordinate> coordinates = ls.getCoordinates();
			Coordinate coordinate = new Coordinate(coordList.get(i).get(0), coordList.get(i).get(1));
			
			coordinates.add(coordinates.size(), coordinate);
			
			
			folder.addToFeature(newFolder);			
			i++;
		}
		Document newDocument = new Document().withName(name);
		newDocument.getFeature().add(folder);
		unmarshal.setFeature(newDocument);
		
		try {
			String s = fileName.substring(0, fileName.length()-4)+".kmz";
			s = fileName;
			// File file = new File(s);
			unmarshal.marshalAsKmz(s);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
public List<Double> getModifiedCoordinates(List<Double> listToModify, List<List<Double>> list){
		
		List<Double> newList = new List<Double>();
		
		//point a modifier
		Double x1 = listToModify.get(0);
		Double y1 = listToModify.get(1);
		
		// premier point de la droite
		Double x2 = list.get(0).get(0);
		Double y2 = list.get(0).get(1);
		
		// deuxième point de la droite
		Double x3 = list.get(1).get(0);
		Double y3 = list.get(1).get(1);
		
		//nouveau point 
		Double x = listToModify.get(0);
		Double y = listToModify.get(1);
		
		Double dx = x3 - x2;
		Double dy = y3 - y2;
		
		if(dx == 0.0){
			x = x2;
		}
		if(dy == 0.0){
			y = y2;
		}
		
		if((dx != 0.0) && (dy != 0.0)){
			
			Double p = dy / dx;
			Double delta = -(p*p+1)/p;
			Double alpha = y2 - p*x2;
			Double beta = y1 + (dx/dy)*x1;
			
			x = (alpha - beta) / delta;
			y = (p*p*beta + alpha) / (p*p+1);			
			
		}		
		newList.add(x);
		newList.add(y);
		return newList;		
		
	}	
	
	
	
	public List<List<Double>> getAdaptedList(List<List<Double>> coordinatesList, List<List<Double>> listToModify){
		
		List<List<Double>> modifiedList = new List<List<Double>>();
		
		List<Double> firstPoint = listToModify.get(0);
		List<Double> lastPoint = listToModify.get(listToModify.size()-1);
		
		List<List<Double>> firstSegment = new List<List<Double>>();
		List<List<Double>> lastSegment = new List<List<Double>>();
		
		firstSegment.add(coordinatesList.get(0));
		firstSegment.add(coordinatesList.get(1));
		
		lastSegment.add(coordinatesList.get(firstSegment.size()-1));
		lastSegment.add(coordinatesList.get(firstSegment.size()-2));
		
		modifiedList.add(getModifiedCoordinates(firstPoint, firstSegment));
		for(int i=1;i<listToModify.size()-2;i++){
			modifiedList.add(listToModify.get(i));
		}
		modifiedList.add(getModifiedCoordinates(lastPoint, lastSegment));
		
		return modifiedList;
	}
	
	public List<String> getDates(Integer from, Integer To){
		
		List<String> dates =new List<String>();
		for(Integer i=from;i<To+1;i++){
			
			Integer date = i;
			dates.add(date.toString());
		}
		return dates;
	}
}
