/***************************************************************************
 *   Copyright (C) 2004 by David Sansome                                   *
 *   me@davidsansome.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 __helios_H__
#define __helios_H__

#include <qdialog.h>
#include <kscreensaver.h>
#include <kdialogbase.h>
#include <qslider.h>
#include <qgl.h>
#include "rsMath.h"
#include "rgbhsl.h"
#include "impCubeVolume.h"
#include "impCrawlPoint.h"
#include "impSphere.h"
#include "heliossetup.h"

#define myRandf(x) (((float)(x) * random()) / 2147483647)
#define myRandi(x) (int)(myRandf(x))
#define fabstrunc(f) (f >= 0.0f ? (f <= 1.0f ? f : 1.0f) : (f >= -1.0f ? -f : 1.0f))

#define PIx2 6.28318530718f
#define PI 3.14159265359f
#define LIGHTSIZE 64


struct HeliosParams
{
	int dIons;
	int dSize;
	int dEmitters;
	int dAttracters;
	int dSpeed;
	int dCameraspeed;
	int dBlur;
	bool dSurface;
	bool dWireframe;
};


class particle
{
public:
	rsVec pos;
	rsVec rgb;
	float size;
};


class emitter : public particle
{
public:
	rsVec oldpos;
	rsVec targetpos;

	emitter();
	~emitter() {}
	void settargetpos(rsVec target) {oldpos = pos; targetpos = target;}
	void interppos(float n) {pos = oldpos * (1.0f - n) + targetpos * n;}
	void update() {}
};


class attracter : public particle
{
public:
	rsVec oldpos;
	rsVec targetpos;

	attracter();
	~attracter() {}
	void settargetpos(rsVec target) {oldpos = pos; targetpos = target;}
	void interppos(float n) {pos = oldpos * (1.0f - n) + targetpos * n;}
	void update() {}
};

class HeliosWidget;

class ion : public particle
{
public:
	float speed;

	ion();
	~ion() {}
	void start();
	void update();
	void draw();
};


class HeliosWidget : public QGLWidget
{
	Q_OBJECT

public:
	HeliosWidget( QWidget* parent, const char* name, HeliosParams p );
	~HeliosWidget();

protected:
	void paintGL();
	void resizeGL( int w, int h );
	void initTexture(int w, int h);
	void initializeGL();

private slots:
	void nextFrame();

public:
	void setTargets(int whichTarget);
	
	int _frameTime;
	QTimer* _timer;
	
	unsigned char lightTexture[LIGHTSIZE][LIGHTSIZE];
	float elapsedTime;
	emitter *elist;
	attracter *alist;
	ion *ilist;
	rsVec newRgb;
	float billboardMat[16];
	bool pfd_swap_exchange;
	bool pfd_swap_copy;
	int ionsReleased;
	float releaseTime;
	float oldCameraDistance;
	float cameraDistance;
	float targetCameraDistance;
	float preCameraInterp;
	int thisTime, lastTime;
	
	rsVec radialVel;
	rsVec targetRadialVel;
	rsQuat rotQuat;
	rsVec oldHsl, newHsl, targetHsl;
	float colorInterp, colorChange;
	float wait;
	float preinterp, interp;
	float interpconst;
	int newTarget, lastTarget;
	float valuetrig;
	
	impCubeVolume* volume;
	impSurface* surface;
	impSphere* spheres;
	
	HeliosParams params;
};

HeliosWidget* currentWidget;

class KHeliosScreenSaver : public KScreenSaver
{
	Q_OBJECT
	
public:
	KHeliosScreenSaver( WId id );
	KHeliosScreenSaver( WId id, HeliosParams p );
	virtual ~KHeliosScreenSaver();
	
	HeliosParams params;
	
private:
	void readSettings();
	
	HeliosWidget* _effect;
};



class KHeliosSetup : public KDialogBase
{
	Q_OBJECT

public:
	KHeliosSetup( QWidget* parent = 0, const char* name = 0 );
	~KHeliosSetup();

private slots:
	void slotHelp();
	void slotOk();
	void slotDefault();
	void slotApply();
	void resetTimer();
	void updatePreview();

private:
	void saveSettings();
	
	HeliosSetup* setupWidget;
	QWidget* preview;
	KHeliosScreenSaver* _saver;
	QTimer* timer;
};

#endif
