// 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/KmlParser.h"

#include "android/base/StringParse.h"

#include <libxml/parser.h>

#include <string>
#include <utility>

#include <string.h>
#include <unistd.h>

using std::string;

// Coordinates can be nested arbitrarily deep within a Placemark, depending
// on the type of object (Point, LineString, Polygon) the Placemark contains
static xmlNode* findCoordinates(xmlNode* current) {
    for (; current != nullptr; current = current->next) {
        if (!strcmp((const char *) current->name, "coordinates")) {
            return current;
        }
        xmlNode * children = findCoordinates(current->xmlChildrenNode);
        if (children != nullptr) {
            return children;
        }
    }
    return nullptr;
}

// Coordinates have the following format:
//        <coordinates> -112.265654928602,36.09447672602546,2357
//                ...
//                -112.2657374587321,36.08646312301303,2357
//        </coordinates>
// often entirely contained in a single string, necessitating regex
static bool parseCoordinates(xmlNode* current, GpsFixArray* fixes) {
    xmlNode* coordinates_node = findCoordinates(current);
    bool result = true;
    if (coordinates_node == nullptr ||
        coordinates_node->xmlChildrenNode == nullptr ||
        coordinates_node->xmlChildrenNode->content == nullptr) {
        return false;
    }

    const char* coordinates = (const char*)(coordinates_node->xmlChildrenNode->content);
    int coordinates_len = strlen(coordinates);
    int offset = 0, n = 0;
    GpsFix new_fix;
    while(3 == android::base::SscanfWithCLocale(
                      coordinates + offset,
                      "%f , %f , %f%n",
                      &new_fix.longitude,
                      &new_fix.latitude,
                      &new_fix.elevation,
                      &n)) {
        fixes->push_back(new_fix);
        offset += n;
    }

    // Only allow whitespace at the end of the string to remain unconsumed.
    for (int i = offset; i < coordinates_len && result; ++i) {
        result = isspace(coordinates[i]);
    }

    return result;
}

static bool parseGxTrack(xmlNode* children, GpsFixArray* fixes) {
    bool result = true;
    for (xmlNode* current = children; result && current != nullptr; current = current->next) {
        if (
            current->ns &&
            current->ns->prefix &&
            !strcmp((const char*)current->ns->prefix, "gx") &&
            !strcmp((const char *)current->name, "coord")) {
            std::string coordinates{(const char*)current->xmlChildrenNode->content};
            GpsFix new_fix;
            result = (3 == android::base::SscanfWithCLocale(
                                  coordinates.c_str(),
                                  "%f %f %f",
                                  &new_fix.longitude,
                                  &new_fix.latitude,
                                  &new_fix.elevation));
            fixes->push_back(new_fix);
        }
    }
    return result;
}

static bool parsePlacemark(xmlNode* current, GpsFixArray* fixes) {
    string description;
    string name;
    size_t ind = string::npos;
    // not worried about case-sensitivity since .kml files
    // are expected to be machine-generated
    for (; current != nullptr; current = current->next) {
        const bool hasContent =
                current->xmlChildrenNode && current->xmlChildrenNode->content;

        if (hasContent && !strcmp((const char*)current->name, "description")) {
            description = (const char*)current->xmlChildrenNode->content;
        } else if (hasContent && !strcmp((const char*)current->name, "name")) {
            name = (const char *) current->xmlChildrenNode->content;
        } else if (
                !strcmp((const char *) current->name, "Point") ||
                !strcmp((const char *) current->name, "LineString") ||
                !strcmp((const char *) current->name, "Polygon")) {
            ind = (ind != string::npos ? ind :fixes->size());
            if (!parseCoordinates(current->xmlChildrenNode, fixes)) {
                return false;
            }
        } else if (
            current->ns &&
            current->ns->prefix &&
            !strcmp((const char*)current->ns->prefix, "gx") &&
            !strcmp((const char*)current->name, "Track")) {
            ind = (ind != string::npos ? ind :fixes->size());
            if (!parseGxTrack(current->xmlChildrenNode, fixes)) {
                return false;
            }
        }
    }

    if (ind == string::npos || ind >= fixes->size()) {
        return false;
    }

    // only assign name and description to the first of the
    // points to avoid needless repetition
    (*fixes)[ind].description = std::move(description);
    (*fixes)[ind].name = std::move(name);

    return true;
}

// Placemarks (aka locations) can be nested arbitrarily deep
static bool traverseSubtree(xmlNode* current,
                                        GpsFixArray* fixes,
                                        string* error) {
    for (; current; current = current->next) {
        if (current->name != nullptr &&
                !strcmp((const char *) current->name, "Placemark")) {

            if (!parsePlacemark(current->xmlChildrenNode, fixes)) {
                *error = "Location found with missing or malformed coordinates";
                return false;
            }
        } else if (current->name != nullptr &&
                strcmp((const char *) current->name, "text")) {

            // if it's not a Placemark we must go deeper
            if (!traverseSubtree(current->xmlChildrenNode, fixes, error)) {
                return false;
            }
        }
    }
    error->clear();
    return true;
}

bool KmlParser::parseFile(const char * filePath, GpsFixArray * fixes, string * error) {
    // This initializes the library and checks potential ABI mismatches between
    // the version it was compiled for and the actual shared library used.
    LIBXML_TEST_VERSION

    xmlDocPtr doc = xmlReadFile(filePath, nullptr, 0);
    if (doc == nullptr) {
        *error = "KML document not parsed successfully.";
        xmlFreeDoc(doc);
        return false;
    }

    xmlNodePtr cur = xmlDocGetRootElement(doc);
    if (cur == nullptr) {
        *error = "Could not get root element of parsed KML file.";
        xmlFreeDoc(doc);
        xmlCleanupParser();
        return false;
    }
    bool isWellFormed = traverseSubtree(cur, fixes, error);

    xmlFreeDoc(doc);
    xmlCleanupParser();

    return isWellFormed;
}
