#ifndef _DEALER_H_
#define _DEALER_H_

#include "pile.h"
#include "hint.h"
#include <tqdom.h>
#include <krandomsequence.h>

class TQDomDocument;
class TDEMainWindow;
class Dealer;
class DealerInfo;
class TDEAction;
class TDESelectAction;
class TDEToggleAction;
class KPixmap;

class DealerInfoList {
public:
    static DealerInfoList *self();
    void add(DealerInfo *);

    const TQValueList<DealerInfo*> games() const { return list; }
private:
    TQValueList<DealerInfo*> list;
    static DealerInfoList *_self;
};

class DealerInfo {
public:
    DealerInfo(const char *_name, int _index)
        : name(_name),
          gameindex(_index)
{
    DealerInfoList::self()->add(this);
}
    const char *name;
    uint gameindex;
    virtual Dealer *createGame(TDEMainWindow *parent) = 0;
};

class CardState {
public:
    Card *it;
    Pile *source;
    double x;
    double y;
    double z;
    bool faceup;
    bool tookdown;
    int source_index;
    CardState() {}
public:
    // as every card is only once we can sort after the card.
    // < is the same as <= in that context. == is different
    bool operator<(const CardState &rhs) const { return it < rhs.it; }
    bool operator<=(const CardState &rhs) const { return it <= rhs.it; }
    bool operator>(const CardState &rhs) const { return it > rhs.it; }
    bool operator>=(const CardState &rhs) const { return it > rhs.it; }
    bool operator==(const CardState &rhs) const {
        return (it == rhs.it && source == rhs.source && x == rhs.x &&
                y == rhs.y && z == rhs.z && faceup == rhs.faceup
                && source_index == rhs.source_index && tookdown == rhs.tookdown);
    }
    void fillNode(TQDomElement &e) const {
        e.setAttribute("value", it->rank());
        e.setAttribute("suit", it->suit());
        e.setAttribute("source", source->index());
        e.setAttribute("x", x);
        e.setAttribute("y", y);
        e.setAttribute("z", z);
        e.setAttribute("faceup", faceup);
        e.setAttribute("tookdown", tookdown);
        e.setAttribute("source_index", source_index);
    }
};

typedef TQValueList<CardState> CardStateList;

struct State
{
    CardStateList cards;
    TQString gameData;
};


/***************************************************************

  Dealer -- abstract base class of all varieties of patience

***************************************************************/
class Dealer: public TQCanvasView
{
    TQ_OBJECT
  

public:

    Dealer( TDEMainWindow* parent = 0, const char* name = 0 );
    virtual ~Dealer();

    static const Dealer *instance();

    void enlargeCanvas(TQCanvasRectangle *c);
    void setGameNumber(long gmn);
    long gameNumber() const;

    virtual bool isGameWon() const;
    virtual bool isGameLost() const;

    void setViewSize(const TQSize &size);

    void addPile(Pile *p);
    void removePile(Pile *p);

    virtual bool checkRemove( int checkIndex, const Pile *c1, const Card *c) const;
    virtual bool checkAdd   ( int checkIndex, const Pile *c1, const CardList& c2) const;
    virtual bool checkPrefering( int checkIndex, const Pile *c1, const CardList& c2) const;

    virtual Card *demoNewCards();

    virtual void setupActions();

    bool demoActive() const;

    void drawPile(KPixmap &, Pile *p, bool selected);

    TQColor midColor() const { return _midcolor; }
    void setBackgroundPixmap(const TQPixmap &background, const TQColor &midcolor);

    void saveGame(TQDomDocument &doc);
    void openGame(TQDomDocument &doc);

    void setGameId(int id) { _id = id; }
	 int gameId() const { return _id; }

    void setTakeTargetForHints(bool e) { takeTargets = e; }
    bool takeTargetForHints() const { return takeTargets; }

    bool isMoving(Card *c) const;

    virtual TQSize minimumCardSize() const;
    virtual void resizeEvent(TQResizeEvent *);

    int freeCells() const;

    TQString anchorName() const;
    void setAnchorName(const TQString &name);

    void setAutoDropEnabled(bool a);
    bool autoDrop() const { return _autodrop; }

    int getMoves() const { return undoList.count(); }

public slots:

    // restart is pure virtual, so we need something else
    virtual void startNew();
    void undo();
    virtual void takeState();
    virtual bool startAutoDrop();
    void hint();
    void slotTakeState(Card *c);

signals:
    void undoPossible(bool poss);
    void gameWon(bool withhelp);
    void gameLost();
    void saveGame(); // emergency
    void gameInfo(const TQString &info);
    void updateMoves();

public slots:
    virtual void demo();
    void waitForDemo(Card *);
    void toggleDemo();
    virtual void stopDemo();
    void waitForAutoDrop(Card *);

protected:

    enum { None = 0, Hint = 1, Demo = 2, Redeal = 4 } Actions;

    void setActions(int actions) { myActions = actions; }
    int actions() const { return myActions; }

    virtual void restart() = 0;

    virtual void contentsMousePressEvent(TQMouseEvent* e);
    virtual void contentsMouseMoveEvent( TQMouseEvent* );
    virtual void contentsMouseReleaseEvent( TQMouseEvent* );
    virtual void contentsMouseDoubleClickEvent( TQMouseEvent* );
    virtual void wheelEvent( TQWheelEvent *e );

    void unmarkAll();
    void mark(Card *c);
    Pile *findTarget(Card *c);
    virtual bool cardClicked(Card *);
    virtual void pileClicked(Pile *);
    virtual bool cardDblClicked(Card *);
    void won();

    virtual void getHints();
    void newHint(MoveHint *mh);
    void clearHints();
    // it's not const because it changes the random seed
    virtual MoveHint *chooseHint();

    TDEMainWindow *parent() const;

    bool waiting() const { return _waiting != 0; }
    void setWaiting(bool w);

protected:
    PileList piles;

    State *getState();
    void setState(State *);

    // reimplement this to add game-specific information in the state structure
    virtual TQString getGameState() const { return TQString(); }
    // reimplement this to use the game-specific information from the state structure
    virtual void setGameState( const TQString & ) {}

    virtual void newDemoMove(Card *m);

    bool moved;
    CardList movingCards;
    TQCanvasItemList marked;
    TQPoint moving_start;
    Dealer( Dealer& );  // don't allow copies or assignments
    void operator = ( Dealer& );  // don't allow copies or assignments
    TQCanvas myCanvas;
    TQSize minsize;
    TQSize viewsize;
    TQPtrList<State> undoList;
    long gamenumber;
    TQValueList<MoveHint*> hints;
    Card *towait;
    TQTimer *demotimer;
    int myActions;
    bool toldAboutLostGame;

    TDEToggleAction *ademo;
    TDEAction *ahint, *aredeal;

    KRandomSequence randseq;
    TQColor _midcolor;
    TQ_UINT32 _id;
    bool takeTargets;
    bool _won;
    int _waiting;
    bool stop_demo_next;
    TQString ac;
    static Dealer *s_instance;
    bool _autodrop;
    bool _gameRecorded;

private:
	 void countLoss();
	 void countGame();
};

#endif
