//****************************************************************************
//Copyright (C) 2005-2006 Beijing BlueDJ Technology Co.,Ltd. All rights reserved.

//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 (in the file LICENSE.GPL); if not, write to the Free Software
//Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

//Please visit http://www.bluedj.com for more infomation about us.
//Contact us at ggwizard@gmail.com or darkdong@gmail.com.
//****************************************************************************/

#include <QRect>

#include "DJGameController.h"
#include "DJClientRequest.h"
#include "DJGameUser.h"
#include "DJGameRoom.h"
#include "DJTreeWidget.h"
#include "jdebug.h"
#include "panelbase.h"
#include "DJTopWidget.h"
#include "Utility.h"
#include "DJTreeItemDelegate.h"
#include "xqpanel.h"
#include "xqrule.h"
#include "xqprofile.h"
#include "DJGamePlayerItem.h"

void  HandleMoveACL( const QByteArray& buf, const QList<void *>& parameters );
//////////////////////////////////////////////////////////////////////

XiangqiRuleItem::XiangqiRuleItem(Q3Canvas * canvas, QWidget* parent,XiangqiRule *prule):
			QObject(parent)
{
	c_Canvas = canvas;
	c_Desktop= (XiangqiDesktop *)parent;
	if(prule != NULL)
	{
		memcpy(&rule,prule,sizeof(XiangqiRule));
		rule.shBaseTime = ltoh2(prule->shBaseTime);
	}else
	{
		memset(&rule,0,sizeof(XiangqiRule));
	}
	
	c_basictext = NULL;
	c_basictime = NULL;
	c_dumiaotext = NULL;
	c_dumiaotime = NULL;
	c_timestext = NULL;
	c_times = NULL;
	
	CreateItems();
	
	c_timer = new QTimer(parent);
    connect(c_timer,SIGNAL(timeout()),this,SLOT(HandleTimeout()));
	
}
void XiangqiRuleItem::setRule(XiangqiRule *prule)
{
	if(prule != NULL)
	{
		memcpy(&rule,prule,sizeof(XiangqiRule));
		rule.shBaseTime = ltoh2(prule->shBaseTime);
	}else
	{
		memset(&rule,0,sizeof(XiangqiRule));
	}
	char buffer[100];
	sprintf(buffer,"%d:%d:%d",rule.shBaseTime/3600,
				(rule.shBaseTime%3600)/60,(rule.shBaseTime%3600)%60);
	c_basictime->setText(QString(buffer));
	sprintf(buffer,"%d:%d",rule.chTimeAfterBaseTime/60,
					rule.chTimeAfterBaseTime%60);
	c_dumiaotime->setText(QString(buffer));
	sprintf(buffer,"%d-%d:%d",rule.chTimes,
				rule.chTimeAfterTimeout/60,rule.chTimeAfterTimeout%60);
	c_times->setText(QString(buffer));
	
}

void XiangqiRuleItem::CreateItems()
{
	char buffer[100];
	if(c_basictext != NULL)
		delete c_basictext;
	if(c_basictime != NULL)
		delete c_basictime;
	if(c_dumiaotext != NULL)
		delete c_dumiaotext;
	if(c_dumiaotime != NULL)
		delete c_dumiaotime;
	if(c_timestext != NULL)
		delete c_timestext;
	if(c_times != NULL)
		delete c_times;
	
	QFont f;
	c_basictext = new Q3CanvasText(tr("Basic"),c_Canvas);
	c_basictext->setColor(QColor(0,0,0xFF));
	f = c_basictext->font();
	f.setPointSize(10);
	f.setBold(false);
	c_basictext->setFont(f);
	
	sprintf(buffer,"%d:%d:%d",rule.shBaseTime/3600,
				(rule.shBaseTime%3600)/60,(rule.shBaseTime%3600)%60);
	c_basictime = new Q3CanvasText(QString(buffer),c_Canvas);
	c_basictime->setColor(QColor(0xFF,0,0));
	c_basictime->setFont(f);
	
	c_dumiaotext = new Q3CanvasText(tr("Fast"),c_Canvas);
	c_dumiaotext->setColor(QColor(0,0,0xFF));
	c_dumiaotext->setFont(f);
	
	sprintf(buffer,"%d:%d",rule.chTimeAfterBaseTime/60,
				rule.chTimeAfterBaseTime%60);
	c_dumiaotime = new Q3CanvasText(QString(buffer),c_Canvas);
	c_dumiaotime->setColor(QColor(0xFF,0,0));
	c_dumiaotime->setFont(f);
	
	c_timestext = new Q3CanvasText(tr("Reserve"),c_Canvas);
	c_timestext->setColor(QColor(0,0,0xFF));
	c_timestext->setFont(f);
	
	sprintf(buffer,"%d-%d:%d",rule.chTimes,
				rule.chTimeAfterTimeout/60,rule.chTimeAfterTimeout%60);
	c_times = new Q3CanvasText(QString(buffer),c_Canvas);
	c_times->setColor(QColor(0xFF,0,0));
	c_times->setFont(f);
	
}

void XiangqiRuleItem::move(int x,int y)
{
	c_X = x;
	c_Y = y;
	QRect rect;
	int w = c_Desktop->width()-x;
	rect =	c_basictext->boundingRect();
	c_basictext->move(x+((w-rect.width())>>1),y);
	y += 15;
	rect =	c_basictime->boundingRect();
	c_basictime->move(x+((w-rect.width())>>1),y);
	y += 15;
	rect =	c_dumiaotext->boundingRect();
	c_dumiaotext->move(x+((w-rect.width())>>1),y);
	y += 15;
	rect =	c_dumiaotime->boundingRect();
	c_dumiaotime->move(x+((w-rect.width())>>1),y);
	y += 15;
	rect =	c_timestext->boundingRect();
	c_timestext->move(x+((w-rect.width())>>1),y);
	y += 15;
	rect =	c_times->boundingRect();
	c_times->move(x+((w-rect.width())>>1),y);
}

void XiangqiRuleItem::show()
{
	c_basictext->show();
	c_basictime->show();
	c_dumiaotext->show();
	c_dumiaotime->show();
	c_timestext->show();
	c_times->show();
	
}
void XiangqiRuleItem::hide()
{
	c_basictext->hide();
	c_basictime->hide();
	c_dumiaotext->hide();
	c_dumiaotime->hide();
	c_timestext->hide();
	c_times->hide();
}

void XiangqiRuleItem::startTimer()
{
	c_iStart = time(NULL);
	c_iElps = 0;
	c_timer->start(1000,false);
}

void XiangqiRuleItem::stopTimer()
{
	c_timer->stop();
}

void XiangqiRuleItem::HandleTimeout()
{
	char buffer[100];
	int ispace = time(NULL)-c_iStart;
	if(ispace > c_iElps)
		ispace = ispace-c_iElps;
	else
		return;
	c_iElps += ispace;
	if(rule.shBaseTime > ispace)
	{
		rule.shBaseTime -= ispace;
	}else
	{
		if(rule.shBaseTime != 0)
		{
			ispace -= rule.shBaseTime;
			rule.shBaseTime = 0;
		}
		if(rule.chTimeAfterBaseTime > ispace)
		{
			rule.chTimeAfterBaseTime -= ispace;
			if ( rule.chTimeAfterBaseTime <= 10 )
				c_Desktop->c_Panel->playWave( QString("number%1.wav").arg(rule.chTimeAfterBaseTime) );
		}else if(rule.chTimes > 0)
		{
			ispace -= rule.chTimeAfterBaseTime;
			rule.chTimeAfterBaseTime = 0;
			rule.chTimes --;
			rule.chTimeAfterBaseTime += (rule.chTimeAfterTimeout-ispace);
		}
	}
	sprintf(buffer,"%d:%d:%d",rule.shBaseTime/3600,
				(rule.shBaseTime%3600)/60,(rule.shBaseTime%3600)%60);
	c_basictime->setText(QString(buffer));
	sprintf(buffer,"%d:%d",rule.chTimeAfterBaseTime/60,
					rule.chTimeAfterBaseTime%60);
	c_dumiaotime->setText(QString(buffer));
	sprintf(buffer,"%d-%d:%d",rule.chTimes,
				rule.chTimeAfterTimeout/60,rule.chTimeAfterTimeout%60);
	c_times->setText(QString(buffer));
	
	c_timer->start(1000,false);
}
XiangqiRuleItem::~XiangqiRuleItem()
{
}

////////////////////////////////////////////////////////////////////////

#define XIANGQI_BOARD_MAX_HEIGHT			750
#define XIANGQI_BOARD_MAX_WIDTH				675
#define XIANGQI_CHIP_MAX_SIZE				75

#define DESKTOP_IMAGE_TYPE_AVATOR			0x101
#define DESKTOP_IMAGE_TYPE_BOARD			0x102

#define DESKTOP_IMAGE_TYPE_CHIP				0x110
#define DESKTOP_IMAGE_TYPE_RED				0x110
#define DESKTOP_IMAGE_TYPE_BLACK			0x111
#define DESKTOP_IMAGE_TYPE_FOCUS			0x120
#define DESKTOP_IMAGE_ISCHIP(__type)			((__type)== DESKTOP_IMAGE_TYPE_RED || (__type)==DESKTOP_IMAGE_TYPE_BLACK)

XiangqiDesktop::XiangqiDesktop(Q3Canvas * canvas, QWidget* parent,XiangqiPanel *panel):
				Q3CanvasView(canvas,parent)
{
	c_Canvas = canvas;
	c_Panel = panel;
	
	c_pbStart = new QPushButton(tr("Start"),this);
	connect(c_pbStart,SIGNAL(released()),this,SLOT(ClickStart()));
	c_pbStart->hide();

	c_pbSur = new QPushButton(tr("Surrender"),this);
	connect(c_pbSur,SIGNAL(released()),this,SLOT(ClickSurrender()));
	c_pbSur->hide();
	c_pbDues = new QPushButton(tr("Request Dues"),this);
	connect(c_pbDues,SIGNAL(released()),this,SLOT(ClickDues()));
	c_pbDues->hide();
	
	c_Canvas->setDoubleBuffering(TRUE);
    c_Canvas->setAdvancePeriod(300);
	setVScrollBarMode(AlwaysOff);
    setHScrollBarMode(AlwaysOff);
	
	c_paTimer = InitTimerMovie();
	itemTimer = new Q3CanvasSprite( c_paTimer,c_Canvas);
		itemTimer->hide();
		itemTimer->setFrameAnimation ( );
		itemTimer->setAnimated(TRUE);
		itemTimer->setZ(2000);
	
	c_MoveTimer = new QTimer(this);
    connect(c_MoveTimer,SIGNAL(timeout()),this,SLOT(HandleMoveTimeout()));
	
	c_shSkin = 1;
	memset(&c_Board,0,sizeof(XiangQiBoard));
	c_itemBoard = NULL;
	
	c_selfRule = new XiangqiRuleItem(c_Canvas,this,NULL);
	c_comRule = new XiangqiRuleItem(c_Canvas,this,NULL);
	
	memset(c_itemAvatar,0,sizeof(CChessImageItem*)*5);
	memset(c_itemName,0,sizeof(Q3CanvasText*)*5);
	c_bRequestDuce[1] = false;
	c_bRequestDuce[2] = false;
	c_bRequestDuce[0] = false;
	
	c_itemFocus = NULL;
	c_itemStartPos	= NULL;
	
	c_Canvas->setBackgroundColor(QColor(75,130,170));
	QPalette pal = palette();
	pal.setBrush(QPalette::Background,QColor(75,130,170));
	setPalette(pal);
	
}

void XiangqiDesktop::GameWait()
{
	int x = width()-102,y;
	if(c_Panel->WaittingForMe())
	{
		y = height()-64;
	}else
	{
		y = 32;
	}
	itemTimer->move(x,y);
	itemTimer->show();
}

void XiangqiDesktop::SetRule(unsigned char chSite,XiangqiRule *prule)
{
	if(chSite == c_Panel->selfSeatId())
		c_selfRule->setRule(prule);
	else
		c_comRule->setRule(prule);
}

void XiangqiDesktop::RequestDuels(unsigned char chSite)
{
	c_bRequestDuce[chSite] = true;
	RepaintAvatar();
}

void XiangqiDesktop::AdjustBoard(const GeneralGameTrace2Head *gameTrace)
{
	memcpy(&c_Board,gameTrace->chBuf,sizeof(XiangQiBoard));
	ClearAllChips();
	int i,j;
	for(i=1;i<=9;i++)
	{
		for(j=1;j<=10;j++)
		{
			DrawChip(i,j);
		}
	}
}

void XiangqiDesktop::RepaintAvatar()
{
	int i,x,y;
	quint32 uid;
	DJGameUser *puser;
	QFont f;
	QPixmap pix;
	QImage  img;
	
	for(i=1;i<=2;i++)
	{
		if(c_itemAvatar[i] != NULL)
			delete c_itemAvatar[i];
		if(c_itemName[i] != NULL)
			delete c_itemName[i];
		c_itemAvatar[i] = NULL;
		c_itemName[i] = NULL;
		GetAvatarPosition(i,&x,&y);
		if(i == c_Panel->selfSeatId())
		{
			c_selfRule->move(x,y-95);
			c_selfRule->show();
		}else
		{
			c_comRule->move(x,y+70);
			c_comRule->show();
		}
		uid = c_Panel->userIdOfSeat(i);
		puser = c_Panel->gameUser(uid,false);
		if(puser != NULL)
		{
			c_itemName[i] = new Q3CanvasText(puser->userName(),c_Canvas);
			c_itemName[i]->setColor(QColor(0,0,0));
			f = c_itemName[i]->font();
			f.setPointSize(14);
			f.setBold(true);
			c_itemName[i]->setFont(f);
			x = 0;y=0;
			GetUserNamePosition(i,c_itemName[i],&x,&y);
			c_itemName[i]->move(x,y);
			c_itemName[i]->show();
			if(c_bRequestDuce[i])
				pix = QPixmap(QString(":/ChineseChessRes/image/pigeon.png"));
			else
				pix = puser->avatar();
        	img = pix.convertToImage();
        	img = img.smoothScale(64,64);
			GetAvatarPosition(i,&x,&y);
        	c_itemAvatar[i] = new CChessImageItem(img,c_Canvas,0,i,DESKTOP_IMAGE_TYPE_AVATOR);
			c_itemAvatar[i]->move(x,y);
			c_itemAvatar[i]->show();
		}
		
	}
}

void XiangqiDesktop::RepaintBoard()
{
	int w,h,w1,h1;
	if(c_itemBoard != NULL)
		delete c_itemBoard;
	ClearAllChips();
	w = width();
	h = height();
	w1 = w-64;
	h1 = (w1*10)/9;
	if(h1 > h-60)
	{
		h1 = h-60;
		w1 = (h1*9)/10;
	}
	if(h1 > XIANGQI_BOARD_MAX_HEIGHT)
	{
		h1 = XIANGQI_BOARD_MAX_HEIGHT;
		w1 = XIANGQI_BOARD_MAX_WIDTH;
	}
	c_Fx = (w1*100)/XIANGQI_BOARD_MAX_WIDTH;
	
	w1 = XIANGQI_BOARD_MAX_WIDTH*c_Fx/100;
	h1 = XIANGQI_BOARD_MAX_HEIGHT*c_Fx/100;
	
	c_X = (w-64-w1)>>1;
	c_Y = (h-h1)>>1;
	QPixmap pix = QPixmap(QString(":/ChineseChessRes/image/cchessb%1.png").arg(c_shSkin));
	if(pix.isNull())
	{
		DEBUG_OUTPUT(("no board%d\n",c_shSkin));
		return;
	}
	QImage img = pix.convertToImage();
    img = img.smoothScale(w1,h1);
	c_itemBoard = new CChessImageItem(img,c_Canvas,0,0,DESKTOP_IMAGE_TYPE_BOARD);
	c_itemBoard->move(c_X,c_Y);
	c_itemBoard->setZ(100);
	c_itemBoard->show();
	
	int i,j;
	for(i=1;i<=9;i++)
	{
		for(j=1;j<=10;j++)
		{
			DrawChip(i,j);
		}
	}
	
	if(c_itemFocus != NULL)
		delete c_itemFocus;
	pix = QPixmap(QString(":/ChineseChessRes/image/focus.png"));
    img = pix.convertToImage();
	img = img.smoothScale(XIANGQI_CHIP_MAX_SIZE*c_Fx/100,XIANGQI_CHIP_MAX_SIZE*c_Fx/100);
    c_itemFocus = new CChessImageItem(img,c_Canvas,0,0,DESKTOP_IMAGE_TYPE_FOCUS);
	c_itemFocus->setZ(3000);
	c_itemFocus->hide();
	
	if(c_itemStartPos != NULL)
		delete c_itemStartPos;
	pix = QPixmap(QString(":/ChineseChessRes/image/start.png"));
    img = pix.convertToImage();
	img = img.smoothScale(XIANGQI_CHIP_MAX_SIZE*c_Fx/100,XIANGQI_CHIP_MAX_SIZE*c_Fx/100);
    c_itemStartPos = new CChessImageItem(img,c_Canvas,0,0,DESKTOP_IMAGE_TYPE_FOCUS);
	c_itemStartPos->setZ(3000);
	c_itemStartPos->hide();
}

void XiangqiDesktop::DrawChip(unsigned char x,unsigned char y)
{
	int s,nx,ny;
	unsigned char chChip;
	char pixname[255];

	chChip = XiangQi_GetNode(&c_Board,x,y);
	if(chChip != 0)
	{
		QPixmap pix;
		QImage img;
		
		s = XIANGQI_CHIP_MAX_SIZE*c_Fx/100;
		GetNodeXY(x,y,&nx,&ny);
		nx -= (s>>1);
		ny -= (s>>1);
		sprintf(pixname,":/ChineseChessRes/image/chips%d/%02x.png",c_shSkin,chChip);
		pix = QPixmap(QString(pixname));
		img = pix.convertToImage();
    	img = img.smoothScale(s,s);
		CChessImageItem *item = new CChessImageItem(img,c_Canvas,x,y,DESKTOP_IMAGE_TYPE_CHIP+(chChip>>3));
		item->move(nx,ny);
		item->setZ(200);
		item->show();
	}
}

void XiangqiDesktop::ClearChip(unsigned char x,unsigned char y)
{
	CChessImageItem * item=GetChipOfNode(x,y);
	if(item != NULL)
		delete item;
}

void XiangqiDesktop::ClearAllChips()
{
	Q3CanvasItemList list = c_Canvas->allItems();
    Q3CanvasItemList::Iterator it = list.begin();
	CChessImageItem *item;
    while(it != list.end())
    {
    	if((*it)->rtti() == imageRTTI )
		{
			item = (CChessImageItem *)(*it);
        	if ( DESKTOP_IMAGE_ISCHIP(item->c_chType) )
           	 	delete item;
        }
		it++;
    }
}
CChessImageItem * XiangqiDesktop::GetChipOfNode(unsigned char x,unsigned char y)
{
	int nx,ny;
	CChessImageItem *item;
	
	GetNodeXY(x,y,&nx,&ny);
	QPoint p(nx,ny);

	Q3CanvasItemList l=canvas()->collisions(p);
	Q3CanvasItemList::Iterator it=l.begin();
	while(it != l.end())
	{
		if((*it)->rtti() == imageRTTI )
		{
			item = (CChessImageItem *)(*it);
			if(DESKTOP_IMAGE_ISCHIP(item->c_chType))
			{
				return item;
			}
		}
		it ++;
	}
	return NULL;
}


void XiangqiDesktop::GetNodeXY(unsigned char x,unsigned char y,int *px,int *py)
{
	int nx,ny;
	nx = XIANGQI_CHIP_MAX_SIZE*(x-1)+(XIANGQI_CHIP_MAX_SIZE>>1);
	ny = XIANGQI_CHIP_MAX_SIZE*(10-y)+(XIANGQI_CHIP_MAX_SIZE>>1);
	if(c_Panel->selfSeatId() != c_Panel->c_Current.chRed)
	{
		nx = XIANGQI_BOARD_MAX_WIDTH-nx;
		ny = XIANGQI_BOARD_MAX_HEIGHT-ny;
	}
	nx = nx * c_Fx/100;
	ny = ny * c_Fx/100;
	
	if(nx < 0 || nx > XIANGQI_BOARD_MAX_WIDTH || ny < 0 || ny >XIANGQI_BOARD_MAX_HEIGHT)
	{
		*px = 0;
		*py = 0;
	}else
	{
		*px = nx+c_X;
		*py = ny+c_Y;
	}
	
}

void XiangqiDesktop::resizeEvent( QResizeEvent * )
{
	c_Canvas->resize(width(),height());
	//c_pbStart->setGeometry( (width()-64)>>1,(height()>>1)+35,80,30);
	//c_pbDues->setGeometry((width()-70),(height()>>1)-30,65,25);
	//c_pbSur->setGeometry((width()-70),(height()>>1)+5,65,25);
	c_pbStart->move( (width()-c_pbStart->width())>>1,(height()>>1)+35);
	c_pbDues->move((width()-c_pbDues->width()),(height()>>1)-30);
	c_pbSur->move((width()-c_pbSur->width()),(height()>>1)+5);
	RepaintAvatar();
	RepaintBoard();	
}

void XiangqiDesktop::contentsMouseReleaseEvent(QMouseEvent* e)
{
	CChessImageItem *item;
	if(c_Panel->isLookingOn() || !c_Panel->IsWaitMove() || !c_bMove || c_bWaitACL)
		return;

	QPoint pp = inverseWorldMatrix().map(e->pos());
//	if (e->button() == Qt::LeftButton) 
	{
		unsigned char x,y;
		if(pp.x()<c_X || pp.y()<c_Y)
		{
			if(c_itemFocus != NULL)
				c_itemFocus->hide();
			if(c_itemStartPos != NULL)
				c_itemStartPos->hide();
			return ;
		}
		x = (pp.x()-c_X)/(XIANGQI_CHIP_MAX_SIZE*c_Fx/100)+1;
		y = ((pp.y()-c_Y)/(XIANGQI_CHIP_MAX_SIZE*c_Fx/100)+1);
		if(x > 9 || y > 10)
		{
			if(c_itemFocus != NULL)
				c_itemFocus->hide();
			if(c_itemStartPos != NULL)
				c_itemStartPos->hide();
			return ;
		}
		y = 11-y;
		if(c_Panel->selfSeatId() != c_Panel->c_Current.chRed)
		{
			x = 10-x;
			y = 11-y;
		}
		DEBUG_OUTPUT(("x=%d,y=%d ",x,y));
		unsigned char chChip = XiangQi_GetNode(&c_Board,x,y);
		DEBUG_OUTPUT(("%02x\n",chChip));
		if(chChip != 0 && ( (XIANGQI_GETOWNER(chChip) == DJGAME_XIANGQI_RED && 
					c_Panel->selfSeatId() == c_Panel->c_Current.chRed)
				|| (XIANGQI_GETOWNER(chChip) == DJGAME_XIANGQI_BLACK && 
					c_Panel->selfSeatId() == c_Panel->c_Current.chBlack)) )
		{//自己的棋子
			c_chStartPoint = 0;
			item = GetChipOfNode(x,y);
			if(item != NULL)
			{
				c_chStartPoint = XIANGQI_RULE_GETNODEID(x,y);
				c_Panel->playWave("click.wav");
				if(c_itemFocus != NULL)
				{
					int nx,ny;
					GetNodeXY(x,y,&nx,&ny);
					c_itemFocus->move(nx-(c_itemFocus->width()>>1),
										ny-(c_itemFocus->height()>>1) );
					c_itemFocus->show();
				}
			}
		}else if(c_chStartPoint != 0)
		{//目标点
			unsigned char chEndID = XIANGQI_RULE_GETNODEID(x,y);
			unsigned char owner;
			if(c_Panel->selfSeatId() == c_Panel->c_Current.chRed)
				owner = DJGAME_XIANGQI_RED;
			else if(c_Panel->selfSeatId() == c_Panel->c_Current.chBlack)
				owner = DJGAME_XIANGQI_BLACK;
			else
				return;
			if(XIANGQI_SUCCESS(XiangQi_Move(&c_Board,owner,c_chStartPoint,chEndID)))
			{//发送
				DEBUG_OUTPUT(("move success\n"));
				unsigned char buffer[30];
				GeneralGameTrace2Head *pmovet;
				PXiangQiMove			pmove;
				pmovet = (GeneralGameTrace2Head *)buffer;
				pmovet->chTable = c_Panel->selfTableId();
				pmovet->chSite = c_Panel->selfSeatId();
				pmovet->chType = XIANGQI_GAMETRACE_MOVE;
				pmovet->chBufLen = sizeof(XiangQiMove);
				pmove = (PXiangQiMove )pmovet->chBuf;
				pmove->chStart = c_chStartPoint;
				pmove->chEnd = chEndID;
				c_bWaitACL = true;
				QByteArray buf	= c_Panel->makeGameData( DJGAME_PROTOCOL_SUBTYPE_GAMETRACE2,QByteArray((char *)buffer,sizeof(GeneralGameTrace2Head)+pmovet->chBufLen) );
				QList<void *> parameters;
				parameters << this;
				DJClientRequest request( buf ,HandleMoveACL,parameters);
				item = GetChipOfNode(XIANGQI_RULE_GETX(c_chStartPoint),XIANGQI_RULE_GETY(c_chStartPoint));
				if(c_itemFocus != NULL)
					c_itemFocus->hide();
				if(c_itemStartPos != NULL)
					c_itemStartPos->hide();
				c_Panel->sendRequest( request ,false);
				//c_bWaitACL = true;
			}else
			{
				DEBUG_OUTPUT(("invalid move\n"));
			}
		}
	}
}

void  HandleMoveACL( const QByteArray& buf, const QList<void *>& parameters )
{
    PDJGameProtocol pacl = (PDJGameProtocol)buf.data();
    XiangqiDesktop *desktop	= (XiangqiDesktop *)parameters.at(0);
    
	desktop->c_bWaitACL = false;
    if(buf.size() == 0)
    {
        return ;
    }
    if( DJGAME_SUCCESS(pacl->chBuf[0]) )
	{
		desktop->c_bMove = false;
	}
}

void XiangqiDesktop::PlayerMove(unsigned char chSite,unsigned char chStart,unsigned char chEnd)
{
	unsigned char chStartChip = XiangQi_GetNode(&c_Board,XIANGQI_RULE_GETX(chStart),XIANGQI_RULE_GETY(chStart));
	unsigned char chEndChip = XiangQi_GetNode(&c_Board,XIANGQI_RULE_GETX(chEnd),XIANGQI_RULE_GETY(chEnd));
	
	
	ClearChip(XIANGQI_RULE_GETX(chStart),XIANGQI_RULE_GETY(chStart));
	ClearChip(XIANGQI_RULE_GETX(chEnd),XIANGQI_RULE_GETY(chEnd));
	XiangQi_SetNodeByID(&c_Board,chStart,0,0);
	XiangQi_SetNodeByID(&c_Board,chEnd,chStartChip&0x07,chStartChip&0x08);
	DrawChip(XIANGQI_RULE_GETX(chEnd),XIANGQI_RULE_GETY(chEnd));
	
	if(c_itemFocus != NULL)
	{
		int nx,ny;
		GetNodeXY(XIANGQI_RULE_GETX(chEnd),XIANGQI_RULE_GETY(chEnd),&nx,&ny);
		c_itemFocus->move(nx-(c_itemFocus->width()>>1),
				ny-(c_itemFocus->height()>>1) );
		c_itemFocus->show();
		
		GetNodeXY(XIANGQI_RULE_GETX(chStart),XIANGQI_RULE_GETY(chStart),&nx,&ny);
		c_itemStartPos->move(nx-(c_itemStartPos->width()>>1),
				ny-(c_itemStartPos->height()>>1) );
		c_itemStartPos->show();
	}
	if(IsJiangJun(chEnd) )
		c_Panel->playWave("jiang.wav");
	else if(chEndChip != 0)
		c_Panel->playWave("kill.wav");
	else
		c_Panel->playWave("move.wav");
}

bool XiangqiDesktop::IsJiangJun(unsigned char chEnd)
{
	unsigned char chChip = XiangQi_GetNodeByID(&c_Board,chEnd);
	unsigned char owner = (XIANGQI_GETOWNER(chChip)==DJGAME_XIANGQI_RED)?DJGAME_XIANGQI_BLACK:DJGAME_XIANGQI_RED;
	bool bFind=false;
	unsigned char i=8,x,y,j,chJiangPos;
	if(owner == DJGAME_XIANGQI_RED)
	{
		i = 1;
	}
	//先找到老将的位置
	for(x=4;x<=6;x++)
	{
		for(y=i;y<=i+2;y++)
		{
			chChip = XiangQi_GetNode(&c_Board,x,y);
			if(chChip == (XIANGQI_CHIP_JIANG | owner) )
			{
				bFind = true;
				break;
			}
		}
		if(bFind)
			break;
	}
	if(bFind)
	{
		//printf("jiang pos %d,%d\n",x,y);
		chJiangPos = XIANGQI_RULE_GETNODEID(x,y);
		chChip = XiangQi_GetNodeByID(&c_Board,chEnd);
		if(XIANGQI_SUCCESS(XiangQi_Move(&c_Board,XIANGQI_GETOWNER(chChip),chEnd,chJiangPos)))
		{
			//printf("jiang!\n");
			return true;
		}
	}
	return false;
	
}
void XiangqiDesktop::contentsDragMoveEvent ( QDragMoveEvent * e )
{
}
void XiangqiDesktop::WaitMove()
{
	c_pbSur->show();
	c_pbDues->show();
	if(c_Panel->WaittingForMe())
	{
		c_selfRule->startTimer();
		c_comRule->stopTimer();
		c_bMove = true;
		c_bWaitACL = false;
		c_chStartPoint = 0;
	}else
	{
		c_comRule->startTimer();
		c_selfRule->stopTimer();
	}
}

void XiangqiDesktop::WaitStart()
{
	c_pbSur->hide();
	c_pbDues->hide();
	if(c_Panel->WaittingForMe())
	{
		c_pbStart->show();
		c_bRequestDuce[1] = false;
		c_bRequestDuce[2] = false;
		c_bRequestDuce[0] = false;
		RepaintAvatar();
	}else
		c_pbStart->hide();
	
}

void XiangqiDesktop::ClickStart()
{
	c_pbStart->hide();
	//c_wHelp->setText( tr("waiting for other player"));
	QByteArray buf	= c_Panel->makeGameData( DJGAME_PROTOCOL_SUBTYPE_START, QByteArray() );
	DJClientRequest request( buf );
		
    c_Panel->sendRequest( request,false );
	
	if(c_strSaveFile.isEmpty())
		c_strSaveFile = GetTempSaveFileName(DJGAME_XIANGQI);
	InitSaveFileHead(c_Panel,c_strSaveFile,DJGAME_XIANGQI,XIANGQI_GAMETRACE_MOVE);
	
}
bool XiangqiDesktop::hasStarted()
{
	return !c_pbStart->isVisible();
}
void XiangqiDesktop::ClickSurrender()
{
	GeneralGameTrace2Head sur;
	sur.chTable = c_Panel->selfTableId();
	sur.chType = XIANGQI_GAMETRACE_SURRENDER;
	sur.chSite = c_Panel->selfSeatId();
	sur.chBufLen = 0;
	QByteArray buf	= c_Panel->makeGameData( DJGAME_PROTOCOL_SUBTYPE_GAMETRACE2,QByteArray((char *)&sur,sizeof(GeneralGameTrace2Head)) );
	DJClientRequest request( buf);
	c_Panel->sendRequest( request ,false);
}
void XiangqiDesktop::ClickDues()
{
	GeneralGameTrace2Head sur;
	sur.chTable = c_Panel->selfTableId();
	sur.chType = XIANGQI_GAMETRACE_REQUESTDUELS;
	sur.chSite = c_Panel->selfSeatId();
	sur.chBufLen = 0;
	QByteArray buf	= c_Panel->makeGameData( DJGAME_PROTOCOL_SUBTYPE_GAMETRACE2,QByteArray((char *)&sur,sizeof(GeneralGameTrace2Head)) );
	DJClientRequest request( buf);
	c_Panel->sendRequest( request ,false);
}

void XiangqiDesktop::HandleTimeout()
{
}

void XiangqiDesktop::HandleMoveTimeout()
{
}

void XiangqiDesktop::GetAvatarPosition(unsigned char chSite,int *x,int *y)
{
	*x = width()-70;
	if(c_Panel->selfSeatId() == chSite)
	{
		*y = height()-70;
	}else
	{
		*y = 5;
	}
}
void XiangqiDesktop::GetUserNamePosition(unsigned char chSite,Q3CanvasText *item,int *x,int *y)
{
	QRect rect = item->boundingRect();
	*x = width()-75-rect.width();
	if(c_Panel->selfSeatId() == chSite)
	{
		*y = height()-5-rect.height();
	}else
	{
		*y = 5;
	}
	
}

void XiangqiDesktop::GetTimerPosition(unsigned char chSite,int *x,int *y)
{
}

XiangqiDesktop::~XiangqiDesktop()
{
	if(!c_strSaveFile.isNull())
	{
		QFile file(c_strSaveFile);
		file.remove();
	}
}


//////////////////////////////////////////////////////////////////////////
XiangqiPanel::XiangqiPanel( DJGameController *gameController, DJGameRoom *room, const QList<quint32>& userIds, quint8 tableId, quint8 seatId, QWidget * parent, Qt::WFlags f)
			: DJGamePanel( gameController, room, userIds, tableId, seatId, parent, f )
{
	//char chDbgFile[60];
	
	//sprintf(chDbgFile,"Xiangqi_%d_%d.dbg",tableId,seatId);
	//DEBUG_INITFILE((chDbgFile));
	QSplitter* mainSplitter = new QSplitter(Qt::Horizontal , this);
	setCentralWidget( mainSplitter );
	m_leftSplitter = new QSplitter(Qt::Vertical , mainSplitter);
	QSplitter *rightSplitter = new QSplitter(Qt::Vertical , mainSplitter);
	
	c_Ad = new DJTopWidget(rightSplitter);
	
	c_DesktopCanvas = new  Q3Canvas(this);
	c_DesktopCanvas->resize(100,100);
	c_Desktop = new XiangqiDesktop(c_DesktopCanvas,rightSplitter,this);
	
	/*
	QList<PosColor> selfColor;
    PosColor	pc1	= { 0, QColor(224,238,255) };
    PosColor	pc2	= { 0.5, QColor(144,194,255) };
    PosColor	pc3	= { 1, QColor(224,238,255) };
    selfColor << pc1 << pc2 << pc3;
    QList<PosColor> otherColor;
    PosColor	pc5	= { 0, Qt::white };
    PosColor	pc6	= { 1, QColor(225,225,225) };
    otherColor << pc5 << pc6;
	c_PlayerList->setItemDelegate(new DJTreeItemDelegate(selfUserId(),selfColor,otherColor,this));
	c_PlayerList->setMinimumWidth(150);
    c_PlayerList->setMaximumWidth(300);
	c_PlayerList->setMinimumHeight(200);
	
	c_PlayerList->setRootIsDecorated(false);
	QStringList headerSections;
    headerSections << tr("name") << tr("score")<< tr("seat") <<"-";
    c_PlayerList->setColumnCount( headerSections.size() );

	QTreeWidgetItem* headerItem	= new QTreeWidgetItem;
    for ( int i = 0; i < headerSections.size(); i++) {
    	headerItem->setTextAlignment( i, Qt::AlignHCenter );
    	headerItem->setText( i, headerSections.at(i) );
    }
	c_PlayerList->header()->setClickable(false);
	c_PlayerList->setHeaderItem( headerItem );
    c_PlayerList->setSortingEnabled( false );
    */
	memset(&c_Current,0,sizeof(XiangqiCurrent));
	c_Current.chRed = 1;
	c_Current.chBlack = 2;
	/*
	quint32 uid, i;
	for(i=1;i<=room->numberOfSeats();i++)
	{
		uid = userIdOfSeat(i);
		if(c_Current.chRed == i)
			AppendUser2List(this,c_PlayerList,1,uid,XIANGQI_COLOR_RED);
		else 
			AppendUser2List(this,c_PlayerList,1,uid,XIANGQI_COLOR_BLACK);
		SetUserScore(this,c_PlayerList,uid,0,2,true);
	}
	createChatWidget( s2 );
	//showMaximized();
	*/
	//c_Desktop->RepaintAvatar();
	//c_Desktop->RepaintBoard();
	c_chTableStatus = 0;
}
void XiangqiPanel::initialize()
{
	createPlayersWidget( m_leftSplitter );
	createChatWidget( m_leftSplitter );
}
DJGamePlayerItem* XiangqiPanel::addPlayer( quint32 userId, bool isPlayer )
{
	qDebug() << "XiangqiPanel::addPlayer" << userId;
	if ( 0 == userId || 0 == m_playersTreeWidget )
		return 0;
	DJGameUser*	user	= gameUser( userId,true );
	DJGamePlayerItem* playerItem	= gamePlayerItem( userId );
	if ( 0 == playerItem ) {
		playerItem	= createPlayerItem( userId, m_playersTreeWidget );
	}
	if ( isPlayer ) {
		quint8 seatId	= user->seatId();
		QString suffix;
		if( c_Current.chRed == seatId )
			suffix	= tr("[red]");
		else
			suffix	= tr("[black]");
		playerItem->setNameAndSuffix( user->userName(), suffix );
		playerItem->setScore( 0 );
		playerItem->setSeat( user->seatId() );
	}else {
		playerItem->setNameAndSuffix( user->userName(), tr("(looker)") );
		playerItem->setScore( 0 );
		playerItem->setSeat( 0 );
	}
	return playerItem;
}
/*
void XiangqiPanel::lookerIn( quint32 userId, bool in )
{
	DJGamePanel::lookerIn( userId, in );
	if ( in )
		AddUser(this,c_PlayerList,1,userId,0);
	else
		RemoveUser(this,c_PlayerList,userId);
}
*/
void XiangqiPanel::userArrived( quint32 userId, quint8 seatId )
{
	DJGamePanel::userArrived( userId, seatId );
	c_Desktop->RepaintAvatar();
}
void XiangqiPanel::gameInfo( const unsigned char *buf )
{
	bool bRepaint=false;
	XiangqiCurrent *pnc =(XiangqiCurrent*)buf;
	if(pnc->chRed != c_Current.chRed)
		bRepaint = true;
	memcpy(&c_Current,buf,sizeof(XiangqiCurrent));
	if(bRepaint)
	{
		c_Desktop->RepaintBoard();
		
		for(int i=1;i<=gameRoom()->numberOfSeats();i++)
    	{
    		quint32 userId	= userIdOfSeat(i);
    		DJGamePlayerItem* playerItem	= gamePlayerItem( userId );
    		if ( playerItem ) {
    			if(c_Current.chRed == i)
    				playerItem->setNameAndSuffix( QString(), tr("[red]"));
    			else if ( c_Current.chBlack == i )
    				playerItem->setNameAndSuffix( QString(), tr("[black]"));
    		}
    	}
	}
	
}

void XiangqiPanel::gameWait( quint16 mask, quint8 status ,quint16 timeout )
{
	c_chTableStatus = status;
	c_shWaitMask = mask;
	c_iTimeLin = time(NULL)+timeout;
	c_Desktop->GameWait();
	switch(status)
	{
		case DJGAME_TABLE_STATUS_WAITSTART :
			c_Desktop->WaitStart();
			break;
		case DJGAME_XIANGQI_TABLE_STATUS_WAIT_MOVE :
			c_Desktop->WaitMove();
			break;
	}
}
void XiangqiPanel::gameTrace( const GeneralGameTrace2Head *gameTrace )
{
	GeneralGameTrace2Head *trace	= const_cast<GeneralGameTrace2Head *>(gameTrace);
	
	switch( gameTrace->chType ) 
	{
		case XIANGQI_GAMETRACE_ADJUST:
			AppendData2SaveFile(c_Desktop->c_strSaveFile,(char *)gameTrace,sizeof(GeneralGameTrace2Head)+gameTrace->chBufLen);
			c_Desktop->AdjustBoard(gameTrace);
			break;
		case XIANGQI_GAMETRACE_SETRULE :
			AppendData2SaveFile(c_Desktop->c_strSaveFile,(char *)gameTrace,sizeof(GeneralGameTrace2Head)+gameTrace->chBufLen);
			c_Desktop->SetRule(gameTrace->chSite,(XiangqiRule*)gameTrace->chBuf);
			break;
		case XIANGQI_GAMETRACE_MOVE :
		{
			AppendData2SaveFile(c_Desktop->c_strSaveFile,(char *)gameTrace,sizeof(GeneralGameTrace2Head)+gameTrace->chBufLen);
			PXiangQiMove pmove = (PXiangQiMove)gameTrace->chBuf;
			c_Desktop->PlayerMove(gameTrace->chSite,pmove->chStart,pmove->chEnd);
			break;
		}
		case XIANGQI_GAMETRACE_REQUESTDUELS :
		{
			AppendData2SaveFile(c_Desktop->c_strSaveFile,(char *)gameTrace,sizeof(GeneralGameTrace2Head)+gameTrace->chBufLen);
			c_Desktop->RequestDuels(gameTrace->chSite);
			break;
		}
		case XIANGQI_GAMETRACE_REQUESTRULE :
		{
			PXiangqiRule prule = (PXiangqiRule)gameTrace->chBuf;
			//exec rule dialog, and send new rule 2 server
			// by XIANGQI_GAMETRACE_REQUESTRULE
			break;
		}
		case XIANGQI_GAMETRACE_REPEAT :
		{
			AppendData2SaveFile(c_Desktop->c_strSaveFile,(char *)gameTrace,sizeof(GeneralGameTrace2Head)+gameTrace->chBufLen);
			DEBUG_OUTPUT(("repeat %d\n",gameTrace->chBuf[0]));
			break;
		}
	}
}
void XiangqiPanel::magicResult( const MagicResult* magicResult )
{
}
void XiangqiPanel::gameOver( const DJGameOver* gameOver )
{
		QString res;
	int i,score;
	quint32 uid;
	DJGameUser *puser;
	if(gameOver->chSites == 2 && 
		gameOver->site[0].score == gameOver->site[1].score)
	{
		res = tr("dues.");
	}else
	{
		for(i=0;i<gameOver->chSites;i++)
		{
			uid = userIdOfSeat(gameOver->site[i].chSite);
			score = (int)(ltoh4(gameOver->site[i].score));
			//SetUserScore(this,c_PlayerList,uid,score,2,false);
			deltaPlayerScore( uid, score );
			if(uid != 0)
			{
				puser = gameUser(uid,false);
				if(puser != NULL)
				{
					res += puser->userName();
					res += QString(" : %1\n").arg(score);
					puser->changeScore(score);
					if ( score > 0 )
        				puser->increaseWins();
        			else if ( score < 0 ) 
        				puser->increaseLoses();
				}
			}
		}
	}
	appendContent2Browser( res );
	res = tr("Do you want save the battle ?");
	if( QMessageBox::Yes == QMessageBox::information(this,tr("game over"),res,QMessageBox::Yes,QMessageBox::No) )
	{
		QDir dir = QDir::home();
    	if (!dir.exists(QString("DJGameSave")))
		{
		 	dir.mkdir("DJGameSave");
		}
		dir.cd("DJGameSave");
	
		QString filename = QFileDialog::getSaveFileName(
                    this,
                    tr("Save the Battle"),
                    dir.path(),
                    tr("DJGame Save Files(*.sav)"));
		if(filename.isNull())
			return;
		if(!filename.endsWith(QString(".sav")) )
			filename += QString(".sav");
		InitSaveFileHead(this,filename,DJGAME_XIANGQI,XIANGQI_GAMETRACE_MOVE);
		unsigned int iLen = 0;
		char *p = GetSaveData(c_Desktop->c_strSaveFile,DJGAME_XIANGQI,XIANGQI_GAMETRACE_MOVE,&iLen);
		if(p == NULL || iLen == 0)
		{
			DEBUG_OUTPUT(("Cant save the movies\n"));
			return;
		}
		AppendData2SaveFile(filename,p,iLen);
	}
}

bool XiangqiPanel::IsWaitMove()
{
	if(!WaittingForMe())
		return false;
	return (c_chTableStatus == DJGAME_XIANGQI_TABLE_STATUS_WAIT_MOVE);
}

///////////////////////////////////////////////////////
bool XiangqiPanel::WaittingForMe()
{
	if(c_chTableStatus != DJGAME_TABLE_STATUS_WAITSTART &&
			c_chTableStatus != DJGAME_XIANGQI_TABLE_STATUS_WAIT_RULE &&
			c_chTableStatus != DJGAME_XIANGQI_TABLE_STATUS_WAIT_MOVE )
		return false;
	quint16 shMyMask = 1<<(selfSeatId()-1);
	return (shMyMask & c_shWaitMask);
}
/*
void XiangqiPanel::resizeEvent( QResizeEvent * )
{
	s1->setGeometry(0,0,width(),height());
}
*/
void XiangqiPanel::closeEvent( QCloseEvent *e)
{
	if ( isLookingOn() ) {
		//look on
		QByteArray data;
		data.append( selfTableId() );
		QByteArray buf	= makeGameData( DJGAME_PROTOCOL_SUBTYPE_QUITVIEW, data );
		DJClientRequest request( buf );
		sendRequest( request, false );
		e->accept();
		return;
	}
    if( (c_chTableStatus == DJGAME_TABLE_STATUS_WAITSTART || c_chTableStatus == DJGAME_XIANGQI_TABLE_STATUS_WAIT_RULE )
    	&& !c_Desktop->hasStarted() )
    {
    	QByteArray buf	= makeGameData( DJGAME_PROTOCOL_SUBTYPE_QUIT, QByteArray() );
		DJClientRequest request( buf );
		sendRequest( request, false );
		e->accept();
    }else {
    	e->ignore();
    }
			
}
	
XiangqiPanel::~XiangqiPanel()
{
}
