///////////////////////////////////////////////////////////////////////////////
//
//  Copyright (2014) Alexander Stukowski
//
//  This file is part of OVITO (Open Visualization Tool).
//
//  OVITO 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.
//
//  OVITO 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, see <http://www.gnu.org/licenses/>.
//
///////////////////////////////////////////////////////////////////////////////

#pragma once


#include <plugins/pyscript/PyScript.h>
#include <plugins/pyscript/engine/ScriptEngine.h>
#include <core/viewport/overlay/ViewportOverlay.h>

namespace PyScript {

using namespace Ovito;

/**
 * \brief A viewport overlay that runs a Python script which paints into the viewport.
 */
class OVITO_PYSCRIPT_EXPORT PythonViewportOverlay : public ViewportOverlay
{
public:

	/// \brief Constructor.
	Q_INVOKABLE PythonViewportOverlay(DataSet* dataset);

	/// \brief This method asks the overlay to paint its contents over the given viewport.
	virtual void render(Viewport* viewport, QPainter& painter, const ViewProjectionParameters& projParams, RenderSettings* renderSettings) override;

	/// Returns the output generated by the script.
	const QString& scriptOutput() const { return _scriptOutput; }

	/// Returns the Python script function executed by the overlay.
	py::object scriptFunction() {
		if(_overlayScriptFunction)
			return _overlayScriptFunction;
		else
			return py::none();
	}

	/// Sets the Python script function to be executed by the overlay.
	void setScriptFunction(const py::function& func) {
		_overlayScriptFunction = func;
		notifyDependents(ReferenceEvent::TargetChanged);
	}

	/// Returns whether the script was successfully compiled.
	bool compilationSucessful() const {
		return (bool)_overlayScriptFunction;
	}

	/// Loads the default values of this object's parameter fields.
	virtual void loadUserDefaults() override;

protected:

	/// Is called when the value of a property of this object has changed.
	virtual void propertyChanged(const PropertyFieldDescriptor& field) override;

private Q_SLOTS:

	/// Is called when the script generates some output.
	void onScriptOutput(const QString& text);

private:

	/// Compiles the script entered by the user.
	void compileScript();

	/// The Python script.
	DECLARE_MODIFIABLE_PROPERTY_FIELD(QString, script, setScript);

	/// The Python engine.
	std::unique_ptr<ScriptEngine> _scriptEngine;

	/// The output generated by the script.
	QString _scriptOutput;

	/// The compiled script function.
	py::function _overlayScriptFunction;

	Q_CLASSINFO("DisplayName", "Python script");

	Q_OBJECT
	OVITO_OBJECT
};

}	// End of namespace


