/*
 * geolocation.cpp
 * Copyright (C) 2006  Remko Troncon
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

#include "geolocation.h"

#include <QApplication>
#include <QDomDocument>
#include <QDomElement>

GeoLocation::GeoLocation() { }

GeoLocation::GeoLocation(const QDomElement &el) { fromXml(el); }

QDomElement GeoLocation::toXml(QDomDocument &doc)
{
    QDomElement geoloc = doc.createElementNS(PEP_GEOLOC_NS, PEP_GEOLOC_TN);

    if (alt_.hasValue()) {
        QDomElement e = doc.createElement("alt");
        e.appendChild(doc.createTextNode(QString::number(double(alt_.value()))));
        geoloc.appendChild(e);
    }
    if (bearing_.hasValue()) {
        QDomElement e = doc.createElement("bearing");
        e.appendChild(doc.createTextNode(QString::number(double(bearing_.value()))));
        geoloc.appendChild(e);
    }
    if (error_.hasValue()) {
        QDomElement e = doc.createElement("error");
        e.appendChild(doc.createTextNode(QString::number(double(error_.value()))));
        geoloc.appendChild(e);
    }
    if (lat_.hasValue()) {
        QDomElement e = doc.createElement("lat");
        e.appendChild(doc.createTextNode(QString::number(double(lat_.value()))));
        geoloc.appendChild(e);
    }
    if (lon_.hasValue()) {
        QDomElement e = doc.createElement("lon");
        e.appendChild(doc.createTextNode(QString::number(double(lon_.value()))));
        geoloc.appendChild(e);
    }
    if (!datum_.isEmpty()) {
        QDomElement e = doc.createElement("datum");
        e.appendChild(doc.createTextNode(datum_));
        geoloc.appendChild(e);
    }
    if (!description_.isEmpty()) {
        QDomElement e = doc.createElement("description");
        e.appendChild(doc.createTextNode(description_));
        geoloc.appendChild(e);
    }
    if (!country_.isEmpty()) {
        QDomElement e = doc.createElement("country");
        e.appendChild(doc.createTextNode(country_));
        geoloc.appendChild(e);
    }
    if (!region_.isEmpty()) {
        QDomElement e = doc.createElement("region");
        e.appendChild(doc.createTextNode(region_));
        geoloc.appendChild(e);
    }
    if (!locality_.isEmpty()) {
        QDomElement e = doc.createElement("locality");
        e.appendChild(doc.createTextNode(locality_));
        geoloc.appendChild(e);
    }
    if (!area_.isEmpty()) {
        QDomElement e = doc.createElement("area");
        e.appendChild(doc.createTextNode(area_));
        geoloc.appendChild(e);
    }
    if (!street_.isEmpty()) {
        QDomElement e = doc.createElement("street");
        e.appendChild(doc.createTextNode(street_));
        geoloc.appendChild(e);
    }
    if (!building_.isEmpty()) {
        QDomElement e = doc.createElement("building");
        e.appendChild(doc.createTextNode(building_));
        geoloc.appendChild(e);
    }
    if (!floor_.isEmpty()) {
        QDomElement e = doc.createElement("floor");
        e.appendChild(doc.createTextNode(floor_));
        geoloc.appendChild(e);
    }
    if (!room_.isEmpty()) {
        QDomElement e = doc.createElement("room");
        e.appendChild(doc.createTextNode(room_));
        geoloc.appendChild(e);
    }
    if (!postalcode_.isEmpty()) {
        QDomElement e = doc.createElement("postalcode");
        e.appendChild(doc.createTextNode(postalcode_));
        geoloc.appendChild(e);
    }
    if (!text_.isEmpty()) {
        QDomElement e = doc.createElement("text");
        e.appendChild(doc.createTextNode(text_));
        geoloc.appendChild(e);
    }

    return geoloc;
}

void GeoLocation::fromXml(const QDomElement &e)
{
    if (e.tagName() != PEP_GEOLOC_TN)
        return;

    for (QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
        QDomElement m = n.toElement();
        if (m.isNull()) {
            continue;
        }
        if (m.tagName() == "alt")
            alt_ = Maybe<float>(m.text().toFloat());
        else if (m.tagName() == "bearing")
            bearing_ = Maybe<float>(m.text().toFloat());
        else if (m.tagName() == "error")
            error_ = Maybe<float>(m.text().toFloat());
        else if (m.tagName() == "lat")
            lat_ = Maybe<float>(m.text().toFloat());
        else if (m.tagName() == "lon")
            lon_ = Maybe<float>(m.text().toFloat());
        else if (m.tagName() == "datum")
            datum_ = m.text();
        else if (m.tagName() == "description")
            description_ = m.text();
        else if (m.tagName() == "country")
            country_ = m.text();
        else if (m.tagName() == "region")
            region_ = m.text();
        else if (m.tagName() == "locality")
            locality_ = m.text();
        else if (m.tagName() == "area")
            area_ = m.text();
        else if (m.tagName() == "street")
            street_ = m.text();
        else if (m.tagName() == "building")
            building_ = m.text();
        else if (m.tagName() == "floor")
            floor_ = m.text();
        else if (m.tagName() == "room")
            room_ = m.text();
        else if (m.tagName() == "postalcode")
            postalcode_ = m.text();
        else if (m.tagName() == "text")
            text_ = m.text();
    }
}

void GeoLocation::setAlt(float alt) { alt_ = Maybe<float>(alt); }
void GeoLocation::setBearing(float bearing) { bearing_ = Maybe<float>(bearing); }

void GeoLocation::setError(float error) { error_ = Maybe<float>(error); }

void GeoLocation::setLat(float lat) { lat_ = Maybe<float>(lat); }

void GeoLocation::setLon(float lon) { lon_ = Maybe<float>(lon); }

void GeoLocation::setDatum(const QString &datum) { datum_ = datum; }

void GeoLocation::setDescription(const QString &description) { description_ = description; }

const Maybe<float> &GeoLocation::alt() const { return alt_; }

const Maybe<float> &GeoLocation::bearing() const { return bearing_; }

const Maybe<float> &GeoLocation::error() const { return error_; }

const Maybe<float> &GeoLocation::lat() const { return lat_; }

const Maybe<float> &GeoLocation::lon() const { return lon_; }

const QString &GeoLocation::datum() const { return datum_; }

const QString &GeoLocation::description() const { return description_; }

const QString &GeoLocation::country() const { return country_; }

const QString &GeoLocation::region() const { return region_; }

const QString &GeoLocation::locality() const { return locality_; }

const QString &GeoLocation::area() const { return area_; }

const QString &GeoLocation::street() const { return street_; }

const QString &GeoLocation::building() const { return building_; }

const QString &GeoLocation::floor() const { return floor_; }

const QString &GeoLocation::room() const { return room_; }

const QString &GeoLocation::postalcode() const { return postalcode_; }

const QString &GeoLocation::text() const { return text_; }

bool GeoLocation::isNull() const
{
    return !lat_.hasValue() && !lon_.hasValue() && !alt_.hasValue() && !bearing_.hasValue() && !error_.hasValue()
        && country_.isNull() && region_.isNull() && locality_.isNull() && area_.isNull() && street_.isNull()
        && building_.isNull() && floor_.isNull() && room_.isNull() && postalcode_.isNull() && text_.isNull()
        && description_.isNull() && datum_.isNull();
}

bool GeoLocation::operator==(const GeoLocation &o) const
{
    // FIXME
    bool equal = true;
    equal      = equal && (lat_.hasValue() ? lat_.value() == o.lat().value() : !o.lat().hasValue());
    equal      = equal && (lon_.hasValue() ? lon_.value() == o.lon().value() : !o.lon().hasValue());
    equal      = equal && (alt_.hasValue() ? alt_.value() == o.alt().value() : !o.alt().hasValue());
    equal      = equal && (bearing_.hasValue() ? bearing_.value() == o.bearing().value() : !o.bearing().hasValue());
    equal      = equal && (error_.hasValue() ? error_.value() == o.error().value() : !o.error().hasValue());
    equal      = equal && country() == o.country() && region() == o.region() && locality() == o.locality()
        && area() == o.area() && street() == o.street() && datum() == o.datum() && building() == o.building()
        && floor() == o.floor() && room() == o.room() && postalcode() == o.postalcode() && text() == o.text()
        && description() == o.description();
    return equal;
}

bool GeoLocation::operator!=(const GeoLocation &o) const { return !((*this) == o); }

void GeoLocation::setCountry(const QString &s) { country_ = s; }

void GeoLocation::setRegion(const QString &s) { region_ = s; }

void GeoLocation::setLocality(const QString &s) { locality_ = s; }

void GeoLocation::setArea(const QString &s) { area_ = s; }

void GeoLocation::setStreet(const QString &s) { street_ = s; }

void GeoLocation::setBuilding(const QString &s) { building_ = s; }

void GeoLocation::setFloor(const QString &s) { floor_ = s; }

void GeoLocation::setRoom(const QString &s) { room_ = s; }

void GeoLocation::setPostalcode(const QString &s) { postalcode_ = s; }

void GeoLocation::setText(const QString &s) { text_ = s; }

QString GeoLocation::toString() const
{
    QString loc;

    if (alt_.hasValue() || lon_.hasValue() || lat_.hasValue()) {

        loc += QObject::tr("Latitude/Longitude/Altitude: ");

        if (lat_.hasValue())
            loc += QString::number(double(lat_.value())) + "/";
        else
            loc += "0/";

        if (lon_.hasValue())
            loc += QString::number(double(lon_.value())) + "/";
        else
            loc += "0/";

        if (alt_.hasValue())
            loc += QString::number(double(alt_.value()));
        else
            loc += "0";
    }

    if (bearing_.hasValue())
        loc += QObject::tr("\nBearing: ") + QString::number(double(bearing_.value()));

    if (error_.hasValue())
        loc += QObject::tr("\nError: ") + QString::number(double(error_.value()));

    if (!datum().isEmpty())
        loc += QObject::tr("\nDatum: ") + datum();

    if (!country().isEmpty())
        loc += QObject::tr("\nCountry: ") + country();

    if (!postalcode().isEmpty())
        loc += QObject::tr("\nPostalcode: ") + postalcode();

    if (!region().isEmpty())
        loc += QObject::tr("\nRegion: ") + region();

    if (!locality().isEmpty())
        loc += QObject::tr("\nLocality: ") + locality();

    if (!area().isEmpty())
        loc += QObject::tr("\nArea: ") + area();

    if (!street().isEmpty())
        loc += QObject::tr("\nStreet: ") + street();

    if (!building().isEmpty() && (!area().isEmpty() || !street().isEmpty()))
        loc += ", " + building();

    if (!floor().isEmpty())
        loc += QObject::tr("\nFloor: ") + floor();

    if (!room().isEmpty())
        loc += QObject::tr("\nRoom: ") + room();

    if (!description().isEmpty())
        loc += QObject::tr("\nDescription: ") + description();

    if (!text().isEmpty())
        loc += "\n" + text();

    return loc;
}
