/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.sis.internal.storage.gpx;

import java.io.IOException;
import java.util.Collection;
import javax.xml.stream.XMLStreamException;
import javax.xml.bind.JAXBException;
import org.apache.sis.storage.gps.Fix;
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.storage.IllegalFeatureTypeException;
import org.apache.sis.internal.storage.xml.stream.StaxStreamWriter;
import org.apache.sis.internal.feature.AttributeConvention;
import org.apache.sis.internal.feature.Geometries;
import org.apache.sis.util.Version;

// Branch-dependent imports
import org.apache.sis.feature.AbstractFeature;
import org.apache.sis.feature.DefaultFeatureType;


/**
 * Writer for GPX 1.0 and 1.1 files.
 *
 * @author  Johann Sorel (Geomatys)
 * @author  Martin Desruisseaux (Geomatys)
 * @version 0.8
 * @since   0.8
 * @module
 */
final class Writer extends StaxStreamWriter {
    /**
     * The GPX file version: 0 for GPX 1.0 or 1 for GPX 1.1.
     */
    private final int version;

    /**
     * The metadata to write, or {@code null} if none.
     */
    private final Metadata metadata;

    /**
     * Creates a new GPX writer for the given data store.
     *
     * @param  owner     the data store for which this writer is created.
     * @param  metadata  the metadata to write, or {@code null} if none.
     * @throws DataStoreException if the output type is not recognized or the data store is closed.
     * @throws XMLStreamException if an error occurred while opening the XML file.
     * @throws IOException if an error occurred while preparing the output stream.
     */
    public Writer(final Store owner, final Metadata metadata)
            throws DataStoreException, XMLStreamException, IOException
    {
        super(owner);
        this.metadata = metadata;
        final Version ver = owner.version;
        if (ver != null && ver.compareTo(StoreProvider.V1_0, 2) <= 0) {
            version = 0;
        } else {
            version = 1;
        }
    }

    /**
     * Writes the XML declaration followed by GPX metadata.
     * This method shall be invoked exactly once before {@code write(Feature)}.
     *
     * @throws Exception if an error occurred while writing to the XML file.
     */
    @Override
    public void writeStartDocument() throws Exception {
        final String namespace;
        final Version ver;
        switch (version) {
            default:
            case 1: ver = StoreProvider.V1_1; namespace = Tags.NAMESPACE_V11; break;
            case 0: ver = StoreProvider.V1_0; namespace = Tags.NAMESPACE_V10; break;
        }
        super.writeStartDocument();
        writer.setDefaultNamespace(namespace);
        writer.writeStartElement(Tags.GPX);
        writer.writeDefaultNamespace(namespace);
        writer.writeAttribute(Attributes.VERSION, ver.toString());
        if (metadata != null) {
            final String creator = metadata.creator;
            if (creator != null) {
                writer.writeAttribute(Attributes.CREATOR, creator);
            }
            switch (version) {
                default:
                case 1: {
                    /*
                     * In GPX 1.1 format, the metadata are stored under a <metadata> node.
                     * This can conveniently be written by JAXB.
                     */
                    marshal(Tags.NAMESPACE_V11, Tags.METADATA, Metadata.class, metadata);
                    break;
                }
                case 0: {
                    /*
                     * In GPX 1.0 format, the metadata were written inline in the root <gpx> element.
                     * We need to write them ourself. Not all metadata can be written in that legacy format.
                     */
                    writeSingleValue(Tags.NAME,        metadata.name);
                    writeSingleValue(Tags.DESCRIPTION, metadata.description);
                    final Person author = metadata.author;
                    if (author != null) {
                        writeSingleValue(Tags.AUTHOR,  author.name);
                        writeSingleValue(Tags.EMAIL,   author.email);
                    }
                    writeLinks(metadata.links);
                    writeSingle(Tags.TIME, metadata.time);
                    writeList(Tags.KEYWORDS, metadata.keywords);
                    // Really 1.1 namespace below, not 1.0. See 'marshal(…)' javadoc for explanation.
                    marshal(Tags.NAMESPACE_V11, Tags.BOUNDS, Bounds.class, metadata.bounds);
                }
            }
        }
    }

    /**
     * Writes the given feature.
     *
     * @param  feature  the feature to write, or {@code null} if none.
     * @throws DataStoreException if the given feature is not a recognized type.
     * @throws XMLStreamException if underlying STAX writer encounter an error.
     * @throws JAXBException if underlying JAXB marshaller encounter an error.
     */
    @Override
    public void write(final AbstractFeature feature) throws DataStoreException, XMLStreamException, JAXBException {
        if (feature != null) {
            final Types types = ((Store) owner).types;
            final DefaultFeatureType type = feature.getType();
            if (types.wayPoint.isAssignableFrom(type)) {
                writeWayPoint(feature, Tags.WAY_POINT);
            } else {
                final boolean isRoute = types.route.isAssignableFrom(type);
                if (!isRoute && !types.track.isAssignableFrom(type)) {
                    throw new IllegalFeatureTypeException(owner.getLocale(), owner.getFormatName(), type.getName());
                }
                writer.writeStartElement(isRoute ? Tags.ROUTES : Tags.TRACKS);
                writeSingleValue(Tags.NAME,        feature.getPropertyValue(Tags.NAME));
                writeSingleValue(Tags.COMMENT,     feature.getPropertyValue(Tags.COMMENT));
                writeSingleValue(Tags.DESCRIPTION, feature.getPropertyValue(Tags.DESCRIPTION));
                writeSingleValue(Tags.SOURCE,      feature.getPropertyValue(Tags.SOURCE));
                writeLinks((Collection<?>)         feature.getPropertyValue(Tags.LINK));
                writeSingleValue(Tags.NUMBER,      feature.getPropertyValue(Tags.NUMBER));
                if (version != 0) {
                    writeSingleValue(Tags.TYPE,    feature.getPropertyValue(Tags.TYPE));
                }
                if (isRoute) {
                    for (Object prop : (Collection<?>) feature.getPropertyValue(Tags.ROUTE_POINTS)) {
                        writeWayPoint((AbstractFeature) prop, Tags.ROUTE_POINTS);
                    }
                } else {
                    for (Object segment : (Collection<?>) feature.getPropertyValue(Tags.TRACK_SEGMENTS)) {
                        if (segment != null) {
                            writer.writeStartElement(Tags.TRACK_SEGMENTS);
                            for (Object prop : (Collection<?>) ((AbstractFeature) segment).getPropertyValue(Tags.TRACK_POINTS)) {
                                writeWayPoint((AbstractFeature) prop, Tags.TRACK_POINTS);
                            }
                            writer.writeEndElement();
                        }
                    }
                }
                writer.writeEndElement();
            }
        }
    }

    /**
     * Writes a way point, which may be standalone or part of a route or a track segment.
     *
     * @param  feature  feature to write, or {@code null} if none.
     * @param  tagName  way point tag name (can not be {@code null}).
     * @throws XMLStreamException if underlying STAX writer encounter an error.
     * @throws JAXBException if underlying JAXB marshaller encounter an error.
     */
    private void writeWayPoint(final AbstractFeature feature, final String tagName) throws XMLStreamException, JAXBException {
        if (feature != null) {
            final double[] pt = Geometries.getCoordinate(feature.getPropertyValue(AttributeConvention.GEOMETRY));
            if (pt != null && pt.length >= 2) {
                writer.writeStartElement(tagName);
                writer.writeAttribute(Attributes.LATITUDE,  Double.toString(pt[1]));
                writer.writeAttribute(Attributes.LONGITUDE, Double.toString(pt[0]));

                writeSingleValue(Tags.ELEVATION,       feature.getPropertyValue(Tags.ELEVATION));
                writeSingleValue(Tags.TIME,            feature.getPropertyValue(Tags.TIME));
                writeSingleValue(Tags.MAGNETIC_VAR,    feature.getPropertyValue(Tags.MAGNETIC_VAR));
                writeSingleValue(Tags.GEOID_HEIGHT,    feature.getPropertyValue(Tags.GEOID_HEIGHT));
                writeSingleValue(Tags.NAME,            feature.getPropertyValue(Tags.NAME));
                writeSingleValue(Tags.COMMENT,         feature.getPropertyValue(Tags.COMMENT));
                writeSingleValue(Tags.DESCRIPTION,     feature.getPropertyValue(Tags.DESCRIPTION));
                writeSingleValue(Tags.SOURCE,          feature.getPropertyValue(Tags.SOURCE));
                writeLinks((Collection<?>)             feature.getPropertyValue(Tags.LINK));
                writeSingleValue(Tags.SYMBOL,          feature.getPropertyValue(Tags.SYMBOL));
                writeSingleValue(Tags.TYPE,            feature.getPropertyValue(Tags.TYPE));
                writeSingle((Fix)                      feature.getPropertyValue(Tags.FIX));
                writeSingleValue(Tags.SATELITTES,      feature.getPropertyValue(Tags.SATELITTES));
                writeSingleValue(Tags.HDOP,            feature.getPropertyValue(Tags.HDOP));
                writeSingleValue(Tags.VDOP,            feature.getPropertyValue(Tags.VDOP));
                writeSingleValue(Tags.PDOP,            feature.getPropertyValue(Tags.PDOP));
                writeSingleValue(Tags.AGE_OF_GPS_DATA, feature.getPropertyValue(Tags.AGE_OF_GPS_DATA));
                writeSingleValue(Tags.DGPS_ID,         feature.getPropertyValue(Tags.DGPS_ID));

                writer.writeEndElement();
            }
        }
    }

    /**
     * Writes the value of the given enumeration. This method does nothing if the given value is null.
     */
    private void writeSingle(final Fix fix) throws XMLStreamException {
        if (fix != null) {
            writeSingleValue(Tags.FIX, fix.toGPX());
        }
    }

    /**
     * Writes multiple links. This method does nothing if the given list is null.
     *
     * @param  links  the links to write.
     * @throws XMLStreamException if underlying STAX writer encounter an error.
     * @throws JAXBException if underlying JAXB marshaller encounter an error.
     */
    private void writeLinks(final Collection<?> links) throws XMLStreamException, JAXBException {
        if (links != null) {
            for (final Object link : links) {
                if (link != null) {
                    switch (version) {
                        default:
                        case 1: {
                            marshal(Tags.NAMESPACE_V11, Tags.LINK, Link.class, (Link) link);
                            break;
                        }
                        case 0: {
                            writeSingleValue(Tags.URL,      ((Link) link).uri.toASCIIString());
                            writeSingleValue(Tags.URL_NAME, ((Link) link).text);
                            return;                 // GPX 1.0 allows only 1 URL.
                        }
                    }
                }
            }
        }
    }
}
