/***************************************************************************
 *   Copyright (C) 2010 by Volker Lanz <vl@fidra.de>                       *
 *                                                                         *
 *   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, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
 ***************************************************************************/

#include "gui/mapdockwidget.h"

#include "core/activity.h"

#include "fileexport/kmlexporter.h"

#include "veneer/settings.h"

#include <QXmlStreamWriter>
#include <QFile>
#include <QDebug>
#include <QDir>

#include <MarbleWidgetInputHandler.h>
#if MARBLE_VERSION >= 0x000c00
#include <MarbleModel.h>
#endif

#define HAVE_MARBLEWIDGET_RESET_HACK 1

class WorkoutMarbleWidgetInputHandler : public Marble::MarbleWidgetDefaultInputHandler
{
	public:
#if MARBLE_VERSION >= 0x000c00
		WorkoutMarbleWidgetInputHandler(Marble::MarbleWidget* widget) : Marble::MarbleWidgetDefaultInputHandler(widget)
#else
		WorkoutMarbleWidgetInputHandler() : Marble::MarbleWidgetDefaultInputHandler()
#endif
		{
#if MARBLE_VERSION >= 0x000900
			setMouseButtonPopupEnabled(Qt::LeftButton, false);
			setMouseButtonPopupEnabled(Qt::RightButton, false);
#endif
		}
};

MapDockWidget::MapDockWidget(QWidget* parent) :
	QWidget(parent)
{
	setupUi(this);

	init();
	setupConnections();

	initMarbleWidget();
}

MapDockWidget::~MapDockWidget()
{
	Veneer::Settings::self()->setAutoCenterCheckBox(autoCenterCheckBox->isChecked());
	Veneer::Settings::self()->writeConfig();

	QFile::remove(tempFileName());
}

void MapDockWidget::init()
{
	marbleWidget->setShowAtmosphere(false);
	marbleWidget->setShowCrosshairs(false);
	marbleWidget->setShowCompass(false);
	marbleWidget->setShowGrid(false);
	marbleWidget->setShowOverviewMap(false);
	marbleWidget->setShowScaleBar(false);
	marbleWidget->setProjection(Marble::Mercator);

	marbleWidget->setToolTip(QString());
	// TODO: implement RMB menu in WorkoutMarbleWidgetInputHandler
#if MARBLE_VERSION >= 0x000c00
	marbleWidget->setInputHandler(new WorkoutMarbleWidgetInputHandler(marbleWidget));
#else
	marbleWidget->setInputHandler(new WorkoutMarbleWidgetInputHandler());
#endif

	zoomSlider->setMaximum(marbleWidget->maximumZoom());
	zoomSlider->setValue(marbleWidget->zoom());

	autoCenterCheckBox->setChecked(Veneer::Settings::self()->autoCenterCheckBox());
}

void MapDockWidget::initMarbleWidget()
{
	delete marbleWidget;

	marbleWidget = new Marble::MarbleWidget(this);

	marbleWidget->setObjectName(QString::fromUtf8("marbleWidget"));

	QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
	sizePolicy.setHorizontalStretch(3);
	sizePolicy.setVerticalStretch(0);
	sizePolicy.setHeightForWidth(marbleWidget->sizePolicy().hasHeightForWidth());
	marbleWidget->setSizePolicy(sizePolicy);

	marbleWidget->setMinimumSize(QSize(200, 200));

	horizontalLayout->insertWidget(0, marbleWidget);

	marbleWidget->setMapThemeId(QString::fromUtf8("earth/openstreetmap/openstreetmap.dgml"));
	marbleWidget->setShowOverviewMap(false);
	marbleWidget->setShowScaleBar(false);
	marbleWidget->setShowCompass(false);
	marbleWidget->setShowGrid(false);
	marbleWidget->setShowAtmosphere(false);
	marbleWidget->setShowCrosshairs(false);
}

void MapDockWidget::setupConnections()
{
	connect(marbleWidget, SIGNAL(zoomChanged(int)), zoomSlider, SLOT(setValue(int)));

	connect(goHomeButton, SIGNAL(clicked()), this, SLOT(zoomToActivity()));
	connect(zoomInButton, SIGNAL(clicked()), marbleWidget, SLOT(zoomIn()));
	connect(zoomOutButton, SIGNAL(clicked()), marbleWidget, SLOT(zoomOut()));
	connect(zoomSlider, SIGNAL(valueChanged(int)), marbleWidget, SLOT(zoomView(int)));
	connect(moveLeftButton, SIGNAL(clicked()), marbleWidget, SLOT(moveLeft()));
	connect(moveRightButton, SIGNAL(clicked()), marbleWidget, SLOT(moveRight()));
	connect(moveUpButton, SIGNAL(clicked()), marbleWidget, SLOT(moveUp()));
	connect(moveDownButton, SIGNAL(clicked()), marbleWidget, SLOT(moveDown()));

}

void MapDockWidget::zoomToActivity()
{
	if (parentWidget()->isVisible() == false || m_Activity == NULL)
		return;

	double minLat, minLon, maxLat, maxLon;

	if (m_Activity->calcBoundaries(minLat, minLon, maxLat, maxLon))
	{
		marbleWidget->setVisible(false);
		const bool signalState = marbleWidget->blockSignals(true);

		marbleWidget->centerOn((minLon + maxLon) / 2, (minLat + maxLat) / 2);
		marbleWidget->zoomView(marbleWidget->maximumZoom());

		double x, y;
		while (!marbleWidget->screenCoordinates(minLon, minLat, x, y) ||
			!marbleWidget->screenCoordinates(maxLon, minLat, x, y) ||
			!marbleWidget->screenCoordinates(minLon, maxLat, x, y) ||
			!marbleWidget->screenCoordinates(maxLon, maxLat, x, y))
		{
			marbleWidget->zoomViewBy(-100);
		}

		zoomSlider->setValue(marbleWidget->zoom());

		marbleWidget->setVisible(true);
		marbleWidget->blockSignals(signalState);
	}
}

QString MapDockWidget::tempFileName() const
{
	return QString("%1%2workout-marble-widget-%3.kml").arg(QDir::tempPath()).arg(QDir::separator()).arg(QCoreApplication::applicationPid());
}

void MapDockWidget::showMap()
{
	QFile tempFile(tempFileName());

#if defined(HAVE_MARBLEWIDGET_RESET_HACK)
	{
		const int zoom = marbleWidget->zoom();
		const qreal lon = marbleWidget->centerLongitude();
		const qreal lat = marbleWidget->centerLatitude();

		initMarbleWidget();

		// maybe there's an off by one somewhere in the marble widget? need to
		// add 1 or we zoom out each time
		marbleWidget->zoomView(zoom + 1);
		marbleWidget->centerOn(lon, lat);
	}
#else
	marbleWidget->removePlacemarkKey(tempFileName());
#endif

	if (parentWidget()->isVisible() == false || m_Activity == NULL)
	{
		setEnabled(false);
		return;
	}

	setEnabled(true);

	if (!tempFile.open(QIODevice::WriteOnly|QIODevice::Truncate))
	{
		qDebug() << "could not create temporary output file " << tempFileName() << " to draw map";
		return;
	}

	QXmlStreamWriter xml(&tempFile);

	Activities marbleActivities;
	marbleActivities << m_Activity;
	ExporterInterface* e = new KmlExporter(true);

	if (!e->run(xml, marbleActivities))
	{
		qDebug() << "could not export to temporary file to draw map";
		return;
	}

	tempFile.close();

#if MARBLE_VERSION >= 0x000c00
	marbleWidget->model()->addGeoDataFile(tempFileName());
#else
	marbleWidget->addPlacemarkFile(tempFileName());
#endif

	if (autoCenterCheckBox->isChecked())
		zoomToActivity();
}
