#include "GeoImage.h"

#include "Command/DocumentCommands.h"

#include <QtGui/QInputDialog>
#include <QtGui/QMessageBox>

class TrackSegment;

#define WARNING(title, message) { \
	if (warning(MainWindow::tr(title), MainWindow::tr(message).arg(file))) \
		continue; \
	else \
		 return; }

GeoImage::GeoImage(TrackPoint * Pt, QImage img)
: TrackPoint(*Pt), Image(img)
{
}

GeoImage::~GeoImage()
{
}

void GeoImage::draw(QPainter& P, const Projection& theProjection)
{
	
	QPointF me = theProjection.project(position());
	P.setPen(QPen(QColor(0, 0, 0), 2));
	QRectF box(me - QPointF(10, 6), me + QPointF(10, 6));
	P.drawRect(box);
	bound = CoordBox(theProjection.inverse(box.topLeft()), theProjection.inverse(box.bottomRight()));
}
void GeoImage::drawFocus(QPainter& P, const Projection& theProjection)
{
	QPointF me = theProjection.project(position());
	double aspect = (double)Image.height() / (double)Image.width();
	QPointF middle(P.device()->width()*0.2, aspect * P.device()->width()*0.2);
	P.drawImage(QRectF(me - middle, me + middle), Image);
}

/*CoordBox GeoImage::boundingBox(void)
{
	qDebug() << bound.topLeft().lat() << bound.topLeft().lon() << bound.bottomRight().lat();
	if (bound.isNull()) return TrackPoint::boundingBox();
	else return bound;
}*/


void GeoImage::loadImages(QStringList fileNames, MapDocument *theDocument, MapView *theView)
{
	QString file;
	QImage img;
	QDateTime time;
	bool foundTime;

	Exiv2::Image::AutoPtr image;
	Exiv2::ExifData *exifData;
	Exiv2::ExifData::const_iterator i, end;

	MapLayer *theLayer;
	{ // retrieve the target layer from the user
		QStringList layers;
		unsigned int i;
		for (i=0;i<theDocument->layerSize();i++) layers.append(theDocument->getLayer(i)->name());

		bool ok;
		QString layer = QInputDialog::getItem(NULL, MainWindow::tr("Load geotagged Images"),
		 MainWindow::tr("Select the layer to which the images belong:"), layers, 0, false, &ok);
		if (ok && !layer.isEmpty())
			theLayer = theDocument->getLayer(layers.indexOf(layer));
		else
			return;
	}

	CommandList * theList = new CommandList(MainWindow::tr("Loading Images"));

	bool ok;
	int offset = QInputDialog::getInteger( NULL, MainWindow::tr("Set offset"),
	 MainWindow::tr("Specify an offset\n(positive values will position the\nimages more to the end of the track):"),
	 0, 0, (int) ((unsigned int)-1 / 2), 1, &ok);
	if (!ok) offset = 0;

	foreach(file, fileNames) {
		if (!img.load(file))
			WARNING("Image broken", "Cannot open image %1.");

		if (img.isNull())
			continue;

    	image = Exiv2::ImageFactory::open(file.toAscii().constData());
		if (image.get() == 0)
			WARNING("exiv2", "Error with exiv2 in %1.");
		image->readMetadata();

		exifData = &  image->exifData();
		if (exifData->empty())
			WARNING("exif missing", "No exif data in image %1.");
		end = exifData->end();
		foundTime = false;
		for (i = exifData->begin(); i != end; i++) {
			if (i->key() == "Exif.Image.DateTime") {
				time = QDateTime::fromString(i->value().toString().c_str(), "yyyy:MM:dd hh:mm:ss");
				foundTime = true;
			}
		}
		if (!foundTime) WARNING("No timestamp", "Image %1 doesn't provide any time information.");


		time = time.addSecs(offset);

		MapFeature *feature = NULL, *bestFeature = NULL;
		TrackPoint *Pt;
		unsigned int secondsTo = (unsigned int)-1, a;
		unsigned int u;
		for (u=0; u<theLayer->size(); feature = theLayer->get(u++)) {
			if (!feature) { qDebug() << "is this a bug???"; continue; } // TODO
			if (!(Pt = dynamic_cast<TrackPoint*>(feature))) continue;
			a = time.secsTo(Pt->time());
			if (a < secondsTo) { secondsTo = a; bestFeature = feature; }
		}

		if (!bestFeature)
			WARNING("No TrackPoints", "No TrackPoints found for image %1");

		if (secondsTo >= 15)
			if ( QMessageBox::question(NULL, MainWindow::tr("Wrong image?"),
			 MainWindow::tr("Image \"%1\" was taken %2 seconds before the next trackpoint was recorded.\n" \
			 "Do you still want to use it?").arg(file).arg(secondsTo), QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes)
				continue;

		TrackSegment *S;
		int idx;
		if (bestFeature->sizeParents() == 1 &&
		 (Pt = dynamic_cast<TrackPoint*>(bestFeature)) &&
		 (S = dynamic_cast<TrackSegment*>(bestFeature->getParent(0))) )
			idx = S->find(Pt);
		else
			WARNING("Bug?", "Can't access TrackPoint or it's parent or the parent is not a TrackSegment!\n(%1)");

		if (bestFeature->deleteChildren(theDocument, theList)) {
			std::vector<MapFeature*> Alternatives;
			theList->add(new RemoveFeatureCommand(theDocument, Pt, Alternatives));
		}

		GeoImage * GeoPoint = new GeoImage(Pt, QImage(file));
		theList->add(new AddFeatureCommand(theLayer, GeoPoint, false));

		S->add(GeoPoint, idx);
	}
	if (theList->size()) {
		theDocument->addHistory(theList);
		theView->invalidate(true, false);
	}
	else
		delete theList;

}

bool GeoImage::warning(QString title, QString message)
{
	if ( QMessageBox::warning ( NULL, title, message, QMessageBox::Ignore | QMessageBox::Cancel, QMessageBox::Ignore ) == QMessageBox::Ignore)
		return true;
	else
		return false;
}

