/*
 * Copyright (c) 2005 by SilverSoft.Net
 * All rights reserved
 *
 * $Id: gameboard.h,v 0.1 2005/01/08 13:00:57 denis Exp $
 *
 * Author: Denis Kozadaev (denis@silversoft.net)
 * Description:
 *
 * See also: style(9)
 *
 * Hacked by:
 */

#ifndef    __GAME_BOARD_H__
#define    __GAME_BOARD_H__

#include <QWidget>
#include <QPainter>
#include <QPixmap>
#include <QDialog>
#include <QLineEdit>
#include <QTimer>
//Added by qt3to4:
#include <QCloseEvent>
#include <QPaintEvent>
#include <QResizeEvent>
#include <QFocusEvent>
#include <QMouseEvent>
#include <stdlib.h>

#define    MAX(a, b)    (((a) > (b))?(a):(b))
#define    SEP        ' '
#define    EOL        '\n'
#define    LONG_XCHG    "@-@"
#define    SHORT_XCHG    "o-o"
#define    SOCK_WAIT    900
#define    GAMEOVER_TXT    "****"

class GameBoard;
class Drawer;
class Figure;
class GameProtocol;

class GameBoard:public QWidget
{
    Q_OBJECT
public:
    enum GameType {
        NOGAME    = 0x0,
        BLACK    = 0x1,
        WHITE    = 0x2
    };

    enum FigureType {
        NONE        = 0x00,
        WHITE_PAWN    = 0x01,
        WHITE_CASTLE    = 0x02,
        WHITE_BISHOP    = 0x03,
        WHITE_KING    = 0x04,
        WHITE_QUEEN    = 0x05,
        WHITE_KNIGHT    = 0x06,
        BLACK_PAWN    = 0x11,
        BLACK_CASTLE    = 0x12,
        BLACK_BISHOP    = 0x13,
        BLACK_KING    = 0x14,
        BLACK_QUEEN    = 0x15,
        BLACK_KNIGHT    = 0x16,
        DUMMY        = 0xFF
    };

    GameBoard(GameType, const QString &, QWidget *parent = NULL,
        const char *name = NULL);
    GameBoard(int, QWidget *parent = NULL, const char *name = NULL);
    ~GameBoard();

    void        saveImage();

    GameType    type()const{return (gt);}
    QString        status()const{return (my_stat);}

public slots:
    void receiveData(const QString& data);

private:
    Drawer        *drw;
    GameType    gt;
    FigureType    *map;
    QString        hst, my_stat;
    Q3Socket        *sock;
    Q3GroupBox    *box, *hist;
    QListWidget    *lst, *hw, *hb;
    QLineEdit    *edt;
    QTimer        *tmr, *tmr2;
    int        sock_tout;
    GameProtocol* protocol;

    void    initMap();
    void    parseString(const QString&);
    void    updateChat(const QString&);
    void    updateHistory(const QString&, bool);
    void    updateHistory(int, bool);

protected:
    void    resizeEvent(QResizeEvent *);
    void    closeEvent(QCloseEvent *);
    void    focusInEvent(QFocusEvent *);

private slots:
    void    showHostFound();
    void    sockConnected();
    void    sockRead(const QString& data);
    void    sockClosed();
    void    sendMove(const QString&);
    void    sendText();
    void    sendFigure(const QString&, GameBoard::FigureType);
    void    sockTest();
    void    sockError(int);
    void    gameover(int);

signals:
    void    showStatus(const QString&);
    void sendData(const QString& data);
};

//-----------------------------------------------------------------------------

class Drawer:public QWidget
{
    Q_OBJECT
public:
    Drawer(GameBoard::FigureType *, GameBoard::GameType *,
        QWidget *parent = NULL, const char *name = NULL);
    ~Drawer();

    void    makeMove(const QString&);
    void    newFigure(const QString&, int);

private:
    int            top_margin, left_margin, hl;
    int            x_brd, y_brd, cs;
    int            tfx, tfy;
    QPixmap            fig[12];
    GameBoard::FigureType    *map;
    GameBoard::GameType    *gt;
    bool            km, lcm, rcm, kk;

    void    drawBoard(QPainter *, int, int);
    void    drawMap(QPainter *, int, int);
    void    win2map(int&, int&);
    void    map2win(int, int, int&, int&);
    void    takeFigure(int, int);
    void    makeMove(GameBoard::GameType, int, int, int, int, bool, bool);
    bool    xchg(GameBoard::FigureType, GameBoard::FigureType,
            int, int, int, int);
    bool    checkWhiteCastle(int, int, int, int, bool);
    bool    checkBlackCastle(int, int, int, int, bool);

    bool    canTake(int, int);
    bool    hasTakenFigure();
    bool    makeXchg();

protected:
    void    paintEvent(QPaintEvent *);
    void    mousePressEvent(QMouseEvent *);

signals:
    void    touchFigure(int, int);
    void    moved(const QString&);
    void    newFigure(const QString&, GameBoard::FigureType);
    void    gameover(int);
};

//-----------------------------------------------------------------------------

class FigureDialog:public QDialog
{
    Q_OBJECT
public:
    FigureDialog(const QPixmap *, const GameBoard::GameType,
        QWidget *parent = NULL, const char *name = NULL);
    ~FigureDialog();

    GameBoard::FigureType    figure()const{return (fr);}

private:
    GameBoard::GameType    gt;
    const QPixmap        *fig;
    QString            str;
    int            step, fh;
    GameBoard::FigureType    fr;

protected:
    void    paintEvent(QPaintEvent *);
    void    mousePressEvent(QMouseEvent *);
};

//-----------------------------------------------------------------------------

class Figure
{
public:

    static bool    hasMyFigure(GameBoard::GameType,
                GameBoard::FigureType *, int, int, bool);
    static int    hasEnemyFigure(GameBoard::GameType,
                GameBoard::FigureType *, int, int, bool);
    static bool    hasFigure(GameBoard::GameType,
                GameBoard::FigureType *, int, int, bool);
    static int    map2map(GameBoard::GameType, int, int, bool);
    static int    validMove(GameBoard::GameType, GameBoard::FigureType *,
                int, int, int, int, bool);

    static void    moveList(Q3PointArray&, GameBoard::GameType,
                GameBoard::FigureType *, int, int, bool);
    static void    moveListWhitePawn(Q3PointArray&, GameBoard::GameType,
                GameBoard::FigureType *, int, int, bool);
    static void    moveListBlackPawn(Q3PointArray&, GameBoard::GameType,
                GameBoard::FigureType *, int, int, bool);
    static void    moveListCastle(Q3PointArray&, GameBoard::GameType,
                GameBoard::FigureType *, int, int, bool);
    static void    moveListBishop(Q3PointArray&, GameBoard::GameType,
                GameBoard::FigureType *, int, int, bool);
    static void    moveListKing(Q3PointArray&, GameBoard::GameType,
                GameBoard::FigureType *, int, int, bool);
    static void    moveListQueen(Q3PointArray&, GameBoard::GameType,
                GameBoard::FigureType *, int, int, bool);
    static void    moveListKnight(Q3PointArray&, GameBoard::GameType,
                GameBoard::FigureType *, int, int, bool);
    static bool    hasPoint(const Q3PointArray&, int, int);
    static bool    hasKingsMeeting(GameBoard::GameType,
                GameBoard::FigureType *, int, int, bool);
    static bool    validPoint(GameBoard::GameType,
                GameBoard::FigureType *, int, int, bool);
    static QString    map2str(int, int);
    static void    str2map(const QString&, int *, int *);
    static int    checkKing(GameBoard::GameType, GameBoard::FigureType *,
                bool, Q3PointArray&, bool);
};

//-----------------------------------------------------------------------------

class GameProtocol:public QDialog
{
    Q_OBJECT
public:
    void    send(Q3Socket *, const QString&);
    void    setGameType(Q3Socket *, GameBoard::GameType);
    void    acceptGame(Q3Socket *);
    void    sendMove(Q3Socket *, const QString&);
    void    sendQuit(Q3Socket *);
    void    sendText(Q3Socket *, const QString&);
    void    sendFigure(Q3Socket *, const QString&, int);
    void    sendGameover(Q3Socket *, const QString&);
signals:
    void sendData(const QString& data);
};

#endif    /* __GAME_BOARD_H__ */
