package de.hft.stuttgart.citygml.green.alkis;

import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.citygml4j.core.model.core.CityModel;
import org.citygml4j.xml.CityGMLContextException;
import org.citygml4j.xml.reader.CityGMLReadException;
import org.citygml4j.xml.writer.CityGMLWriteException;
import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFinder;
import org.geotools.data.FeatureSource;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.locationtech.jts.geom.MultiPolygon;
import org.locationtech.jts.geom.Polygon;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;

import de.hft.stuttgart.citygml.green.osm.GreenArea;
import de.hft.stuttgart.citygml.green.osm.GreenEnricher;
import de.hft.stuttgart.citygml.green.osm.LandUseArea;
import de.hft.stuttgart.citygml.green.osm.OsmData;
import de.hft.stuttgart.citygml.green.osm.RoadArea;
import de.hft.stuttgart.citygml.green.osm.TreeUtils;
import jakarta.xml.bind.JAXBException;

public class AlkisGreenEnricher {
	
	private static Set<String> greenAreaTypes = new HashSet<>();
	private static Set<String> roadAreaTypes = new HashSet<>();
	
	static {
		greenAreaTypes.add("Wald");
		greenAreaTypes.add("Landwirtschaft");
		greenAreaTypes.add("Friedhof");
		greenAreaTypes.add("Gehölz");
		greenAreaTypes.add("Sport-, Freizeit- und Erholungsfläche");
		
		roadAreaTypes.add("Weg");
		roadAreaTypes.add("Straßenverkehr");
		roadAreaTypes.add("Bahnverkehr");
		
	}
	
	public static void main(String[] args) throws IOException, CityGMLContextException, CityGMLReadException, JAXBException, CityGMLWriteException {
		System.out.println("Reading CityGML file");
		Path inFile = Paths.get(args[0]);
		CityModel cityModel = GreenEnricher.readCityGml(inFile);

		GreenEnricher.createTransformers(cityModel);

		OsmData osmData = new OsmData();
		String boundingBoxString = GreenEnricher.extractAndConvertBoundingBox(cityModel, osmData);
//		HttpResponse<String> response = getOsmData(boundingBoxString);
//		Files.write(Path.of("osm_response.xml"), response.body().getBytes(StandardCharsets.UTF_8));
//		String osmResponse = response.body();
		String osmResponse = Files.readString(Paths.get("data", "osm_response.xml"));

		System.out.println("Parsing OSM response");
		GreenEnricher.parseOsmResponse(osmResponse, osmData);
		
		// ignore green areas from osm
		osmData.getGreenAreas().clear();
		
		parseAlkisData(osmData);


		System.out.println("Fit data in bounding box");
		GreenEnricher.fitToBoundingBox(osmData);
		
		GreenEnricher.convertGreenAreasToCityGML(cityModel, osmData.getGreenAreas());
		GreenEnricher.convertWaterAreasToCityGML(cityModel, osmData);
		GreenEnricher.convertRoadAreasToCityGML(cityModel, osmData);
		GreenEnricher.converLandUseAreasToCityGML(cityModel, osmData);
		
		TreeUtils.insertTrees(cityModel, osmData);

		
		GreenEnricher.clampToGround(cityModel);
		
		String inputString = inFile.getFileName().toString();
		String inputPathWithoutFileEnding = inputString.substring(0, inputString.lastIndexOf('.'));
		Path outputPath = Paths.get("data", inputPathWithoutFileEnding + "_with_alkis_greens.gml");
		System.out.println("Writing output file.");
		GreenEnricher.writeCityGML(cityModel, outputPath);
		System.out.println("Done");


	}

	private static void parseAlkisData(OsmData osmData) throws MalformedURLException, IOException {
		Path alkisDataPath = Paths.get("data", "tn_09663", "Nutzung.shp");
		
		Map<String, Object> readParameters = new HashMap<>();
		readParameters.put("url", alkisDataPath.toUri().toURL());
		readParameters.put("charset", StandardCharsets.UTF_8);
		DataStore dataStore = DataStoreFinder.getDataStore(readParameters);
		String typeName = dataStore.getTypeNames()[0];

		FeatureSource<SimpleFeatureType, SimpleFeature> source = dataStore.getFeatureSource(typeName);

		FeatureCollection<SimpleFeatureType, SimpleFeature> collection = source.getFeatures();
		
		List<GreenArea> greenAreas = osmData.getGreenAreas();
		List<RoadArea> roadAreas = osmData.getRoadAreas();
		List<LandUseArea> landUseAreas = osmData.getLandUseAreas();
		
		try (FeatureIterator<SimpleFeature> features = collection.features()) {
			while (features.hasNext()) {
				SimpleFeature feature = features.next();
				
				MultiPolygon geometry = (MultiPolygon) feature.getAttribute("the_geom");
				String nutzart = feature.getAttribute("nutzart").toString();
				if (geometry.getNumGeometries() > 1) {
					throw new IllegalStateException();
				}
				if (greenAreaTypes.contains(nutzart)) {
					greenAreas.add(new GreenArea((Polygon) geometry.getGeometryN(0)));
				} else if (roadAreaTypes.contains(nutzart)) {
					roadAreas.add(new RoadArea((Polygon) geometry.getGeometryN(0)));
				} else {
					landUseAreas.add(new LandUseArea((Polygon) geometry.getGeometryN(0)));
				}
			}
		}
	}

}
