package org.oskari.map.userlayer.input;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.xml.stream.XMLStreamException;

import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.feature.DefaultFeatureCollection;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.kml.v22.KML;
import org.geotools.kml.v22.KMLConfiguration;
import org.geotools.xml.PullParser;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.xml.sax.SAXException;

import com.vividsolutions.jts.geom.Geometry;

import fi.nls.oskari.log.LogFactory;
import fi.nls.oskari.log.Logger;
import fi.nls.oskari.service.ServiceException;

/**
 * Parse Google KML
 */
public class KMLParser implements FeatureCollectionParser {

    private static final Logger LOG = LogFactory.getLogger(KMLParser.class);

    public static final String SUFFIX = "KML";
    public static final String KML_NAME = "kml_name"; // GML also has name and kml_name is localized to user
    public static final String KML_DESC = "kml_desc"; // GML also has description and kml_desc is localized to user
    public static final String KML_GEOM = "the_geom";

    @Override
    @SuppressWarnings("unchecked")
    public SimpleFeatureCollection parse(File file, CoordinateReferenceSystem sourceCRS,
            CoordinateReferenceSystem targetCRS) throws ServiceException {
        try (InputStream in = new BufferedInputStream(new FileInputStream(file))) {
            /*--- Geotools Parser example ---
            Parser p = new Parser(new KMLConfiguration());
            SimpleFeature doc = (SimpleFeature) p.parse(in);
            List <SimpleFeature> folders = (List<SimpleFeature>) doc.getAttribute("Feature");
            if ("folder".equals(folders.get(0).getType().getTypeName())) {
                List <SimpleFeature> features = (List<SimpleFeature>) folders.get(0).getAttribute("Feature");
                if ("placemark".equals(features.get(0).getType().getTypeName())){
                    // this is placemark
                }
            }
            ---*/
            // Note that this is the happy case where file structure is
            // <Document><Folder><PlaceMark>...</PlaceMark></Folder></Document>
            // Feature can be Document, Folder, PlaceMark, NetworkLink, gx:Tour, PhotoOverlay, ScreenOverlay, GroundOverlay
            // Containers (Document, Folder) can contain Features
            // --> have to loop Features and check the type and if Feature is container then loop it's features...

            // Using PullParser to parse Placemarks only
            PullParser parser = new PullParser(new KMLConfiguration(), in, KML.Placemark);
            SimpleFeature f;
            Set<String> extendedData = new HashSet<String>();
            Map<String, Object> untypedData;

            DefaultFeatureCollection fc = new DefaultFeatureCollection();
            while ((f = (SimpleFeature) parser.parse()) != null) {
                if (f.getUserData().get("UntypedExtendedData") != null) {
                    untypedData = (Map<String, Object>) f.getUserData().get("UntypedExtendedData");
                    untypedData.keySet().forEach((k) -> extendedData.add(k));
                }
                fc.add(f);
            }
            return processFeatures(fc, extendedData);
        } catch (XMLStreamException e) {
            throw new ServiceException("XMLStreamException occured", e);
        } catch (IOException e) {
            throw new ServiceException("IOException occured", e);
        } catch (SAXException e) {
            throw new ServiceException("Invalid KML file: " + e.getMessage());
        }
    }

    @Override
    public String getSuffix() {
        return SUFFIX.toLowerCase();
    }
    @SuppressWarnings("unchecked")
    private DefaultFeatureCollection processFeatures (DefaultFeatureCollection fc_kml, Set<String> extendedData) {
        DefaultFeatureCollection fc = new DefaultFeatureCollection();
        SimpleFeatureBuilder builder;
        SimpleFeature f;
        if (extendedData.isEmpty()){
           builder = getBasicBuilder();
        } else {
           builder = getExtendedBuilder(extendedData);
        }
        SimpleFeatureIterator iter = fc_kml.features();
        while (iter.hasNext()){
            f = iter.next();
            builder.set(KML_NAME, f.getAttribute("name"));
            // Basic builder
            if (extendedData.isEmpty()){
                builder.set(KML_DESC, f.getAttribute("description"));
            // Extended builder
            } else {
                Map<String, Object> untypedData = (Map<String, Object>) f.getUserData().get("UntypedExtendedData");
                if (untypedData != null){
                    extendedData.forEach((k) -> {
                        if (k.equals("description")){
                            builder.set(KML_DESC, untypedData.get(k));
                            return;
                        }
                        builder.set(k, untypedData.get(k));
                    });
                } else if (f.getAttribute("description") != null) {
                    builder.set(KML_DESC, f.getAttribute("description"));
                }
            }
            builder.set(KML_GEOM, f.getDefaultGeometry());
            fc.add(builder.buildFeature(f.getID()));
        }
        return fc;
    }
    private SimpleFeatureBuilder getBasicBuilder () {
        SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
        builder.setName( "BasciKMLBuilder" );
        builder.setNamespaceURI( "http://www.oskari.org" );
        builder.setSRS( "EPSG:4326" );
        builder.add(KML_NAME, String.class );
        builder.add(KML_DESC, String.class );
        builder.add(KML_GEOM, Geometry.class );
        return new SimpleFeatureBuilder(builder.buildFeatureType());
    }
    private SimpleFeatureBuilder getExtendedBuilder (Set<String> extendedData) {
        SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
        builder.setName( "ExtendedKMLBuilder" );
        builder.setNamespaceURI( "http://www.oskari.org" );
        builder.setSRS( "EPSG:4326" );
        builder.add(KML_NAME, String.class );
        if (!extendedData.contains("description")) {
            builder.add(KML_DESC, String.class );
        }
        extendedData.forEach((k) -> {
            if (k.equals("description")){
                builder.add(KML_DESC, String.class );
                return;
            }
            builder.add(k, String.class);
        });
        builder.add(KML_GEOM, Geometry.class );
        return new SimpleFeatureBuilder(builder.buildFeatureType());
    }
}

@@ -4010,97 +4010,8 @@
  %7D%0A%0A
-    @Override%0A    public String getSuffix() %7B%0A        return SUFFIX.toLowerCase();%0A    %7D%0A
     

remove getSuffix