#ifndef MATHEMAGICS_H
#define MATHEMAGICS_H

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <tdeapplication.h>
#include <tqwidget.h>
#include <tqvaluelist.h>
#include <tqptrlist.h>
#include <tdemainwindow.h>
#include <tdeaction.h>
#include <tqmap.h>
#include <tqguardedptr.h>

#include "stacklevel.h"
#include "optiondialog.h"
#include "kparanoidline.h"

class TDEListAction;
class EditAction;
class ComboAction;
class TQComboBox;
class TQCloseEvent;
class TQPushButton;
class TQVBoxLayout;
class TQScrollView;
class TDEToggleAction;
class MathKeypad;

class Mathemagics : public TDEMainWindow
{
	TQ_OBJECT

public:
	/** construtor */
	Mathemagics(TQWidget* parent=0, const char *name=0, WFlags f = 0);
	/** destructor */
	~Mathemagics();

	void updateStack();

protected slots:
	void runFormula(const TQString &);
	bool runCommand(const TQString &);
	void openFile(const TQString &filename);
	void saveFile(const TQString &filename);
	void slotOpen();

	void clearHistory();
	void scrollToBottom();

	void keypadClosing();
	void insertChar(const TQString &);

	void configureToolBars();
	void newToolBarConfig();
	void keyBindings();
	void toggleKeypad(bool);

	void slotEnter();
	void slotAdd();
	void slotSubtract();
	void slotMultiply();
	void slotDivide();
	void slotBackspace();
	void slotKeypadBackspace();

	void slotModulo();
	void slotPercent();
	void slotInverse();
	void slotRaiseE();
	void slotSqrt();
	void slotSquared();
	void slotSine();
	void slotCosine();
	void slotTangent();
	void slotEEX();
	void slotRaiseTen();
	void slotLn();
	void slotFactorial();
	void slotPower();
	void slotNegative();
	void slotAnd();
	void slotOr();
	void slotXOr();
	void slotLsh();
	void slotRsh();
	void slotDup2();
	void slotDrop();

	void slotUpdateStackLevel(int);
	void slotRoll(int);
	void slotRestoreStack();
	void slotRevert();

	void slotPushHighlighted(const TQString&);
	
	void slotConfigure();
	void slotConfigureHide();
	void slotConfigureDestroy();
	void slotUpdateConfiguration();

	void slotBaseChanged(int id);
	void slotAngleChanged(int id);

protected:
	void closeEvent(TQCloseEvent *);
	
private:
	TQPtrList<StackLevel> stackLevels;
	void recreateStackLevels();
	TQScrollView *topLevel;
	TQWidget *boxParent;
	TQVBoxLayout *bigBox;
	EditAction* LineEdit;
	ComboAction* HistoryBox;

	TDEListAction *baseGroup;
	TDEListAction *angGroup;
	TDEListAction *formulae;

	MathKeypad *keypad;

	TQValueList<double> *Stack;
	TQValueList<double> *SavedStack;
	TQStringList entryNums;

	bool parseArgs(unsigned int reqArgs = 0, bool autoEnter = 1, bool save = 1);

	double angConv(const double theDouble);
	double angOut(const double theDouble);
	TQString theAngle();

	int testArgs();
	bool getArgs(unsigned int num);
	TQValueList<double> args;

	double format(TQString theString, bool *ok=0);
	TQString format(double theDouble);

	void saveStack();
	void enter();

	int fact(int n);

	//TQStatusBar *statusBar;
	int dispTime;

	void error();
	void changeStatus(TQString text);
	void changeStatusError(TQString text);
	void changeStatus(double * res, char op);
	void changeStatus(double * res, TQString op, bool prepend = 0);

	void level5Return();
	void level4Return();
	void level3Return();
	void level2Return();
	void level1Return();

	void roll(unsigned int index);
	void rolld(unsigned int index);

	ConfigureDialog * optionDialog;

	//constants
	double pi;

	bool noSave;
	bool enterMode;

	// configuration options
	int numStackLevels;
	bool showPeriod;
	bool fixedPrec;
	int histNum;
	bool histDetail;
	int formatPrec;
	bool toSaveStack;
	bool delDrops;
	int base;
	int angle;
	bool beep;

	TDEToggleAction *keypadAct;
	TDEToggleAction *InvButton;
	TDEToggleAction *HypButton;

	// map names to their formulae
	TQMap<TQString, TQString> formulas;
	TQStringList defFormulas;
	// map names to their help
	TQMap<TQString, TQString> help;

	// variables
	TQMap<TQString, double> variables;
	TQStringList defVariables;
};

class EditAction : public TDEAction
{
  TQ_OBJECT

public:
    EditAction( const TQString& text, int accel, const TQObject *receiver, const char *member, TQObject* parent, const char* name );
    ~EditAction();

    virtual int plug( TQWidget *w, int index = -1 );
    virtual void unplug( TQWidget *w );
    TQString text() { return m_combo? m_combo->text() : TQString::null; }
	TQGuardedPtr<KParanoidLine> edit();

public slots:
	void clear();
	void append(TQString);
	void insert(TQString);

signals:
    void plugged();

private:
    TQGuardedPtr<KParanoidLine> m_combo;
    const TQObject *m_receiver;
    const char *m_member;
};

class ComboAction : public TDEAction
{
  TQ_OBJECT

public:
    ComboAction( const TQString& text, int accel, const TQObject *receiver, const char *member, TQObject* parent, const char* name );
    ~ComboAction();
    virtual int plug( TQWidget *w, int index = -1 );
    virtual void unplug( TQWidget *w );

	TQGuardedPtr<TQComboBox> combo();

signals:
    void plugged();

private:
    TQGuardedPtr<TQComboBox> m_combo;
    const TQObject *m_receiver;
    const char *m_member;
};

#endif
