/***************************************************************************
 *   Copyright (C) 2008 by Peter Dahlberg   *
 *   pdahlberg@gmail.com   *
 *                                                                         *
 *   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.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifndef SIMULSCENE_H
#define SIMULSCENE_H

#include <QGraphicsScene>
#include <graphicsellipseitem.h>
#include <QMap>

class QTimeLine;
class HomoEFieldItem;
class HomoBFieldItem;
class QGraphicsRectItem;
class QGraphicsItemGroup;
class QGraphicsItemAnimation;
class QGraphicsPathItem;
class QPainterPath;
class QListWidget;
class FieldItem;
class StopperItem;

/**
	@author Peter Dahlberg <pdahlberg@gmail.com>
*/
class SimulScene : public QGraphicsScene {
	Q_OBJECT
	public:
		enum SceneMode {
			HomoEFieldItemInsert,
			FieldItemEdit,
			HomoBFieldItemInsert,
			StopperItemInsert,
			ProbeChargeItemPlace
		};
		enum ItemType {ResizeRectItem};
		SimulScene ( QObject* parent = 0);
		qreal getHighestZIndexVisible(); //hoechsten z-index der sichtbaren items 
		qreal getHighestZIndexFieldItems(); //hoechsten z-index der Felder ausgeben
		qreal getLowestZIndexFieldItems(); 

		~SimulScene();
   		double getTimePerStep();
		double getMeterPerPx() const;
		double getPxPerSec() const;
    		int getSteps();

		//! gibt die Wirkende Kraft  zur&uuml;ck (in Newton)
		/*!
			\param point der Punkt der abgepr&uuml;ft werden soll
			\param charge Die Ladung, auf die die Kraft ausge&uuml;bt wird
			\param speedX Aktuelle Geschwindigkeit in x-Richtung
			\param speedY Aktuelle Geschwindigkeit in y-Richtung
			\param xy r&uuml;ckgabe in x oder y-Richtung
		*/
		double getPowerAt(QPointF point, double charge, double speedX, double speedY, char xy);
		bool stopsHere(const QPointF &p1,const QPointF &p2);

   		QWidget* getProbeDockWidget() const;
		
		bool isFlightPathVisible();
		int getTimeLineDuration();
		QListWidget* getFieldListWidget();
		QList<QGraphicsItem*> getItemsInZOrder();
		QList<QGraphicsItem*> getFieldItemsInZOrder();

		GraphicsEllipseItem* getProbeChargeItem();

		void clearFlightPath();

		QList<QVariant> getSaveDataList();
		void setSaveDataList(QList<QVariant> list);
		void connectNewFieldItem(FieldItem* item);
		bool getScenePosLablesActive() const;


	public slots:
		void setSceneMode(SceneMode mode);
		void startTimer();
		void stopTimer();
		void pauseTimer(bool yesno);
		void startPauseTimer(bool yesno);
		void deleteSelectedFieldItems();
   		void setTimePerStep(double time);
		///starte die Berechnung der teilchenbahn(en)
    		void startCalculation();
   		void setSteps(int steps);

		void setMeterPerPx ( double theValue );
		void setPxPerSec ( double theValue );
		void setFlightPathVisible(bool visible = true);
		void setTimeLineDuration(int duration);
		
		void moveFieldItemDown(QGraphicsItem* fieldItem);
		void moveSelectedFieldItemDown();
		void moveFieldItemUp(QGraphicsItem* fieldItem);
		void moveSelectedFieldItemUp();
		void moveFieldItemOnTop(QGraphicsItem* fieldItem);
		void moveSelectedFieldItemOnTop();
		void moveFieldItemOnBottom(QGraphicsItem* fieldItem);
		void moveSelectedFieldItemOnBottom();
		void resetScene();
		void handleTimeLineValueChange(qreal value);

		void setScenePosLablesActive ( bool theValue );
	
	
	private slots:
		void displayResizeRects(bool move = false);
		///does the same as displayResizeRects(true)
		void moveResizeRects();

	signals:
		void sceneModeChanged(int mode);
    		void stepsChanged(int steps);
    		void timePerStepChanged(double timePerStep);
		void meterPerPxChanged(double meterPerPx);
		void pxPerSecChanged(double pxps);
		void flightPathVisibilityChanged(bool visible);
		void timeLineDurationChanged(int duration);
		void timeLineInRunningState(bool yesno = false);
		void realSimulTimeChanged(QString theString);

		void probeSpeedXChanged(QString text);
		void probespeedYChanged(QString text);
		void probeSpeedChanged(QString text);
		void scenePosLablesActiveChanged(bool truefalse);
	private:
		QTimeLine *timer;

		bool scenePosLablesActive;

		SceneMode myMode;

		///Zeit pro Step in sekunden
		double timePerStep;
		///anzahl der Steps
		int steps;
		///ein Pixel entspricht so viel meter
		double meterPerPx;
		///Animationsgescheindigkeit in px/s (durchschnittlich)
		double pxPerSec;


		HomoEFieldItem *currHomoEfieldInsertItem; //Aktuell erstelltes Item
		HomoEFieldItem *currHomoEfieldEditItem;

		HomoBFieldItem *currHomoBfieldInsertItem; //Aktuell erstelltes Item
		HomoBFieldItem *currHomoBfieldEditItem;

		StopperItem *currStopperInsertItem; //Aktuell erstelltes Item
		StopperItem *currStopperEditItem;

		bool ChargePlacementInProgress; //ladung wird gerade platziert

		QGraphicsItem *pressedResizeItem;

		GraphicsEllipseItem *ellipse1;
		QGraphicsItemAnimation *ani;

		QGraphicsPathItem *pathItem1;
		QListWidget* fieldListWidget;
		
		QMap<double, int> aniStepList;

		//rechtecke zur groesenaenderung
		struct resizeRects {
			QGraphicsRectItem *leftTopResizeItem;
			QGraphicsRectItem *leftResizeItem;
			QGraphicsRectItem *leftBottomResizeItem;
			QGraphicsRectItem *bottomResizeItem;
			QGraphicsRectItem *rightBottomResizeItem;
			QGraphicsRectItem *rightRezizeItem;
			QGraphicsRectItem *rightTopResizeItem;
			QGraphicsRectItem *topResizeItem;
		};
		resizeRects reRects;
		void createResizeRects();

		void calculateItemResize(
			QGraphicsSceneMouseEvent *mouseEvent,
			QGraphicsRectItem *pressedRectItem,
			QRectF &currRect,
			QPointF &newPos,
			qreal minWidth,
			qreal minHeight
		);

		QList<HomoEFieldItem*> calcEFieldList;
		QList<HomoBFieldItem*> calcBFieldList;
		QList<StopperItem*> calcStopperList;

		static const qreal FieldDefaultZValue = 10.0; //default z-value fuer Felder
		static const qreal FieldZStep = 1e-10; //schritt, um den der z-index erhoeht wird

		void setupVars();

				

	protected:
		void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent);
		void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent);
		void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent);
		void keyPressEvent ( QKeyEvent * keyEvent );
		void drawBackground ( QPainter * painter, const QRectF & rect );
};

#endif
