// Copyright (C) 2015 The Android Open Source Project
//
// This software is licensed under the terms of the GNU General Public
// License version 2, as published by the Free Software Foundation, and
// may be copied, distributed, and modified under those terms.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

#include "android/gps/GpxParser.h"

#include "android/base/StringParse.h"

#include <libxml/parser.h>

#include <algorithm>
#include <string.h>
#include <time.h>

using std::string;

// format an error message
template <class... Args>
static string formatError(const char* format, Args&&... args) {
    char buf[100] = {};
    snprintf(buf, sizeof(buf) - 1, format, std::forward<Args>(args)...);
    return buf;
}


static void cleanupXmlDoc(xmlDoc *doc)
{
    xmlFreeDoc(doc);
    xmlCleanupParser();
}

static bool parseLocation(xmlNode *ptNode, xmlDoc *doc, GpsFix *result, string *error)
{
    float latitude;
    float longitude;

    xmlAttrPtr attr;
    xmlChar *tmpStr;

    // Check for and get the latitude attribute
    attr = xmlHasProp(ptNode, (const xmlChar *) "lat");
    if (!attr || !(tmpStr = xmlGetProp(ptNode, (const xmlChar *) "lat"))) {
        *error = formatError("Point missing a latitude on line %d.",
                             ptNode->line);
        return false; // Return error since a point *must* have a latitude
    } else {
        int read =
            android::base::SscanfWithCLocale(reinterpret_cast<const char*>(tmpStr), "%f", &latitude);
        xmlFree(tmpStr); // Caller-freed
        if (read != 1) {
            return false;
        }
    }

    // Check for and get the longitude attribute
    attr = xmlHasProp(ptNode, (const xmlChar *) "lon");
    if (!attr || !(tmpStr = xmlGetProp(ptNode, (const xmlChar *) "lon"))) {
        *error = formatError("Point missing a longitude on line %d.",
                             ptNode->line);
        return false; // Return error since a point *must* have a longitude
    } else {
        int read =
            android::base::SscanfWithCLocale(reinterpret_cast<const char*>(tmpStr), "%f", &longitude);
        xmlFree(tmpStr); // Caller-freed
        if (read != 1) {
            return false;
        }
    }

    // The result will be valid if this point is reached
    result->latitude = latitude;
    result->longitude = longitude;

    // Check for potential children nodes (including time, elevation, name, and description)
    // Note that none are actually required according to the GPX format.
    int childCount = 0;
    for (xmlNode *field = ptNode->children; field; field = field->next) {
        tmpStr = nullptr;

        if ( !strcmp((const char *) field->name, "time") ) {
            if ((tmpStr = xmlNodeListGetString(doc, field->children, 1))) {
                // Convert to a number
                struct tm time;
                int results = sscanf((const char *)tmpStr,
                                     "%u-%u-%uT%u:%u:%u",
                                     &time.tm_year, &time.tm_mon, &time.tm_mday,
                                     &time.tm_hour, &time.tm_min, &time.tm_sec);
                if (results != 6) {
                    *error = formatError(
                                 "Improperly formatted time on line %d.<br/>"
                                 "Times must be in ISO format.", ptNode->line);
                    return false;
                }

                // Correct according to the struct tm specification
                time.tm_year -= 1900; // Years since 1900
                time.tm_mon -= 1; // Months since January, 0-11

                result->time = mktime(&time);

                xmlFree(tmpStr); // Caller-freed
                childCount++;
            }
        }
        else if ( !strcmp((const char *) field->name, "ele") ) {
            if ((tmpStr = xmlNodeListGetString(doc, field->children, 1))) {
                int read =
                    android::base::SscanfWithCLocale(reinterpret_cast<const char*>(tmpStr), "%f", &result->elevation);
                xmlFree(tmpStr); // Caller-freed
                if (read != 1) {
                    return false;
                }
                childCount++;
            }
        }
        else if ( !strcmp((const char *) field->name, "name") ) {
            if ((tmpStr = xmlNodeListGetString(doc, field->children, 1))) {
                result->name = reinterpret_cast<const char*>(tmpStr);
                xmlFree(tmpStr); // Caller-freed
                childCount++;
            }
        }
        else if ( !strcmp((const char *) field->name, "desc") ) {
            if ((tmpStr = xmlNodeListGetString(doc, field->children, 1))) {
                result->description = reinterpret_cast<const char*>(tmpStr);
                xmlFree(tmpStr); // Caller-freed
                childCount++;
            }
        }

        // We only care about 4 potential child fields, so quit after finding those
        if (childCount == 4) {
            break;
        }
    }

    return true;
}

static bool parse(xmlDoc *doc, GpsFixArray *fixes, string *error)
{
    xmlNode *root = xmlDocGetRootElement(doc);
    GpsFix location;
    bool isOk;

    for (xmlNode *child = root->children; child; child = child->next) {

        // Individual <wpt> elements are parsed on their own
        if ( !strcmp((const char *) child->name, "wpt") ) {
            isOk = parseLocation(child, doc, &location, error);
            if (!isOk) {
                cleanupXmlDoc(doc);
                return false;
            }
            fixes->push_back(location);
        }

        // <rte> elements require an additional depth of parsing
        else if ( !strcmp((const char *) child->name, "rte") ) {
            for (xmlNode *rtept = child->children; rtept; rtept = rtept->next) {

                // <rtept> elements are parsed just like <wpt> elements
                if ( !strcmp((const char *) rtept->name, "rtept") ) {
                    isOk = parseLocation(rtept, doc, &location, error);
                    if (!isOk) {
                        cleanupXmlDoc(doc);
                        return false;
                    }
                    fixes->push_back(location);
                }
            }
        }

        // <trk> elements require two additional depths of parsing
        else if ( !strcmp((const char *) child->name, "trk") ) {
            for (xmlNode *trkseg = child->children; trkseg; trkseg = trkseg->next) {

                // Skip non <trkseg> elements
                if ( !strcmp((const char *) trkseg->name, "trkseg") ) {

                    // <trkseg> elements an additional depth of parsing
                    for (xmlNode *trkpt = trkseg->children; trkpt; trkpt = trkpt->next) {

                        // <trkpt> elements are parsed just like <wpt> elements
                        if ( !strcmp((const char *) trkpt->name, "trkpt") ) {
                            isOk = parseLocation(trkpt, doc, &location, error);
                            if (!isOk) {
                                cleanupXmlDoc(doc);
                                return false;
                            }
                            fixes->push_back(location);
                        }
                    }
                }
            }
        }
    }

    // Sort the values by timestamp
    std::sort(fixes->begin(), fixes->end());

    cleanupXmlDoc(doc);
    return true;
}

bool GpxParser::parseFile(const char *filePath, GpsFixArray *fixes, string *error)
{
    xmlDocPtr doc = xmlReadFile(filePath, nullptr, 0);
    if (doc == nullptr) {
        cleanupXmlDoc(doc);
        *error = "GPX document not parsed successfully.";
        return false;
    }
    return parse(doc, fixes, error);
}
