#include "GeoImage.h"

#include "Command/DocumentCommands.h"

/*#include <QtGui/QStandardItemModel>
#include <QtGui/QDialog>
#include <QtGui/QListView>
#include <QtGui/QDialogButtonBox>*/
#include <QtGui/QInputDialog>
#include <QtGui/QMessageBox>

class TrackSegment;

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;
	{
		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;

		/*
		QDialog dlg;

   	QVBoxLayout layout(&dlg);
	   QLabel text("Select the layer the images belong to.");
		QListView list(&dlg);
		QStandardItemModel *model = new QStandardItemModel(&list);
		list.setModel(model);
		list.setSelectionMode(QAbstractItemView::SingleSelection);
		QDialogButtonBox buttons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
		layout.addWidget(&text, 0);
		layout.addWidget(&list, 1);
		layout.addWidget(&buttons, 2, Qt::AlignRight);

		dlg.setWindowTitle("Load geotagged Images");

		unsigned int i;
		qDebug() << theDocument->layerSize();
		for (i=0;i<theDocument->layerSize();i++) model->appendRow(new QStandardItem(theDocument->getLayer(i)->name()));
	
		dlg.connect(&buttons, SIGNAL(accepted()), &dlg, SLOT(accept()));
		dlg.connect(&buttons, SIGNAL(rejected()), &dlg, SLOT(reject()));
		if (dlg.exec() != QDialog::Accepted) return;
	
		QModelIndexList selection = list.selectionModel()->selectedRows();
		if (selection.size() != 1) return;
		theLayer = theDocument->getLayer(selection.first().row());

		delete model;
		*/
	}

	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 images more to the end of the track):"),
	 0, 0, (int) ((unsigned int)-1 / 2), 1, &ok);
	qDebug() << (unsigned int)-1 << (int)((unsigned int)-1 /2);
	if (!ok) offset = 0;

	foreach(file, fileNames) {
		if (!img.load(file)) { if (warning(MainWindow::tr("Image broken"), MainWindow::tr("Cannot open image %1.").arg(file))) continue; else return;}
		if (img.isNull()) continue;

    	image = Exiv2::ImageFactory::open(file.toAscii().constData());
		if (image.get() == 0) { qWarning("Error with exiv2 in %s.\n", file.toAscii().constData()); continue; }
		image->readMetadata();

		exifData = &  image->exifData();
		if (exifData->empty()) {
			qWarning("No exif data. Skipping.\n"); continue;
		}
		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");
				qDebug() << "time is" << time;
				foundTime = true;
			}
		}
		if (!foundTime) { if (warning(MainWindow::tr("No timestamp"), MainWindow::tr("Image doesn't provide any time information."))) continue; else return; }


		time = time.addSecs(offset);

		qDebug() << theLayer;
		qDebug() << "theLayer" << theLayer->size();
		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) { qDebug() << "no features found"; continue; }

		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 { qWarning() << "Can't access TrackPoint or it's parent or the parent is not a TrackSegment!\n"; continue; }

		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;
}

