#include "mapview.h"
#include "mapview_tile_cache_p.h"
#include "mapview_tile_downloader_p.h"


MapViewTileDownloader::MapViewTileDownloader(MapView * p): QThread() {
	qRegisterMetaType<MapViewTypes::TileIndex>();
	parent = p;
	start();
}


MapViewTileDownloader::~MapViewTileDownloader() {
	requestInterruption();
	cond.wakeAll();
	wait();
	if (provider) provider->deleteLater();
}


bool MapViewTileDownloader::queueTile(MapViewTypes::TileIndex index, bool force) {
	// auto hash = tile.hash();
	bool ret = false;
	cond_mutex.lock();
	if ((!queue.contains(index) && !in_progress.contains(index.hash())) || force) {
		queue.enqueue(index);
		cond.wakeOne();
		ret = true;
	}
	cond_mutex.unlock();
	return ret;
}


void MapViewTileDownloader::queueTiles(QList<MapViewTypes::TileIndex> indeces) {
	cond_mutex.lock();
	queue << indeces;
	cond.wakeOne();
	cond_mutex.unlock();
}


void MapViewTileDownloader::clearQueue() {
	cond_mutex.lock();
	queue.clear();
	cond_mutex.unlock();
}


void MapViewTileDownloader::setTileProvider(MapViewTileProviderBase * p) {
	if (provider) {
		disconnect(provider, &MapViewTileProviderBase::tileReady, this, &MapViewTileDownloader::tileReady);
		disconnect(provider, &MapViewTileProviderBase::parametersChanged, this, &MapViewTileDownloader::parametersChanged);
		provider->deleteLater();
	}
	provider = p;
	if (provider) {
		connect(provider, &MapViewTileProviderBase::tileReady, this, &MapViewTileDownloader::tileReady);
		connect(provider, &MapViewTileProviderBase::parametersChanged, this, &MapViewTileDownloader::parametersChanged);
	}
	parent->cache->tileProviderChanged();
}


void MapViewTileDownloader::requestTile(MapViewTypes::TileIndex index) {
	if (!provider) return;
	provider->requestTile(index);
}


void MapViewTileDownloader::tileReady(MapViewTypes::TileIndex index, QPixmap pm) {
	if (!pm.isNull()) parent->cache->tileDownloaded(index, pm);
	cond_mutex.lock();
	in_progress.remove(index.hash());
	cond_mutex.unlock();
	emit tileDone();
}


void MapViewTileDownloader::parametersChanged() {
	parent->cache->tileProviderChanged();
}


void MapViewTileDownloader::run() {
	while (!isInterruptionRequested()) {
		cond_mutex.lock();
		if (queue.isEmpty())
			cond.wait(&cond_mutex);
		else {
			auto t = queue.dequeue();
			in_progress.insert(t.hash());
			QMetaObject::invokeMethod(parent, [this, t]() { requestTile(t); }, Qt::QueuedConnection);
		}
		cond_mutex.unlock();
	}
}
