#include "osm_geocoding.h"

#include <QJsonObject>
#include <QJsonValue>
#include <QLocale>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>


OSMGeocodingResult::OSMGeocodingResult(QObject * parent): QObject(parent) {}


OSMGeocodingResult::~OSMGeocodingResult() {}


void OSMGeocodingResult::abort() {
	if (reply) {
		reply->abort();
		reply->deleteLater();
		blockSignals(true);
		deleteLater();
		reply = nullptr;
	}
}


QString OSMGeocodingResult::displayName() const {
	return res.object().value("display_name").toString();
}


QPointF OSMGeocodingResult::resultCoordinate() const {
	auto loc_c = QLocale::c();
	return QPointF(loc_c.toDouble(res.object().value("lat").toString()), loc_c.toDouble(res.object().value("lng").toString()));
}


void OSMGeocodingResult::requestDone() {
	emit ready(this);
	deleteLater();
}


// OSMGeocoding

OSMGeocoding::OSMGeocoding(): QObject() {
	nam      = new QNetworkAccessManager();
	provider = "https://nominatim.openstreetmap.org";
	// https://nominatim.openstreetmap.org/reverse?lat=52.79870&lon=27.56572&format=json
}


OSMGeocoding::~OSMGeocoding() {
	delete nam;
}


OSMGeocoding * OSMGeocoding::instance() {
	static OSMGeocoding ret;
	return &ret;
}


OSMGeocodingResult * OSMGeocoding::queue(QPointF coord) {
	return instance()->reverseCoding(coord);
}


OSMGeocodingResult * OSMGeocoding::reverseCoding(QPointF coord) {
	auto loc_c = QLocale::c();
	QNetworkRequest req(
		provider +
		QString("/reverse?lat=%1&lon=%2&format=json").arg(loc_c.toString(coord.x(), 'f', 8)).arg(loc_c.toString(coord.y(), 'f', 8)));
	req.setHeader(QNetworkRequest::UserAgentHeader, "Qt/5");
	req.setRawHeader("Accept-Language", (QLocale().name() + "," + QLocale().bcp47Name()).toLatin1());
	auto * r = nam->get(req);
	if (!r) return nullptr;
	OSMGeocodingResult * ret = new OSMGeocodingResult(nam);
	ret->reply               = r;
	connect(r, &QNetworkReply::finished, this, [r, ret]() {
		r->deleteLater();
		if (r->error() != QNetworkReply::NoError) {
			qDebug() << "Error:" << r->error();
		} else {
			QByteArray data = r->readAll();
			if (!data.isEmpty()) ret->res = QJsonDocument::fromJson(data);
		}
		ret->requestDone();
	});
	return ret;
}
