//****************************************************************************
//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 "bufalloc.h"
#include "LandBattle.h"
#include "4country.h"
#include "DJTreeItemDelegate.h"
#include "DJMatrixCanvasTimer.h"

#define DESKTOP_IMAGE_TYPE_BOARD		0x101
#define DESKTOP_IMAGE_TYPE_CHIP			0x102
#define DESKTOP_IMAGE_TYPE_AVATOR		0x103
#define DESKTOP_IMAGE_TYPE_DUCE			0x104

void  HandleArrangeACL( const QByteArray& buf, const QVariant& parameters );
void  HandleMoveACL( const QByteArray& buf, const QVariant& parameters );

LandBattleDesktop::LandBattleDesktop(Q3Canvas * canvas, QWidget* parent,LandBattlePanel *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_Canvas->setDoubleBuffering(TRUE);
    c_Canvas->setAdvancePeriod(500);
	
	c_pbSave = new QPushButton(tr("Save Layout"),this);	//Save Scene
	connect(c_pbSave,SIGNAL(released()),this,SLOT(ClickSave()));
	c_pbSave->hide();
	c_pbLoad = new QPushButton(tr("Load Layout"),this);
	connect(c_pbLoad,SIGNAL(released()),this,SLOT(ClickLoad()));
	c_pbLoad->hide();
	c_pbSend = new QPushButton(tr("Send"),this);
	connect(c_pbSend,SIGNAL(released()),this,SLOT(ClickSend()));
	c_pbSend->hide();
	
	c_itemBoard = NULL;
	RepaintChessmap(c_Panel->GetCurrentPlayers());
	
	c_pArrangeNode1 = NULL;
	c_pArrangeNode2 = NULL;
	
	c_timerExchange = new QTimer();
	c_timerExchange->setSingleShot(true);
    connect(c_timerExchange,SIGNAL(timeout()),this,SLOT(HandleExchangeTimeout()));
	
	//c_paTimer = InitTimerMovie();
	//itemTimer = NULL;
	//itemTimerText = NULL;
	//c_timer = new QTimer(this);
    //connect(c_timer,SIGNAL(timeout()),this,SLOT(HandleTimeout()));
	m_clockItem 	= new DJMatrixCanvasTimer( canvas, QString(BASE_RES_DIR) + "/image/movie/timer.gif");
	m_clockItem->setZ(3000);
	m_clockItem->hide();
	
	c_MoveTimer = new QTimer(this);
    connect(c_MoveTimer,SIGNAL(timeout()),this,SLOT(HandleMoveTimeout()));
	c_X = 90;
	c_Y = 0;
	
	c_bWaitACL = false;
	
	c_PlayerMoveNodeStart = NULL;
	c_PlayerMoveNodeEnd = NULL;
	
	c_pMoveTempEnd = NULL;
	setMouseTracking(true);
	
	c_pbSurrender= new QPushButton(tr("Surrender"),this);	
	connect(c_pbSurrender,SIGNAL(released()),this,SLOT(ClickSurrender()));
	c_pbDuce= new QPushButton(tr("Draw"),this);	
	connect(c_pbDuce,SIGNAL(released()),this,SLOT(ClickDuce()));
	
	memset(c_itemDuce,0,sizeof(LandBattleImageItem*)*8);
	memset(c_itemProtrait,0,sizeof(LandBattleImageItem*)*8);
	memset(c_itemName,0,sizeof(Q3CanvasText*)*8);
	
	int i;
	for(i=0;i<8;i++)
		c_bRequestDuce[i] = false;
	
}

void LandBattleDesktop::RepaintPlayer()
{
	DJGameUser *puser;
	quint32 uid, i,chMapSite;
	QPixmap pix;
	QImage  img;
	int x,y;
	
	QFont f;
	for(i=1;i<=c_Panel->c_Room->numberOfSeats();i++)
	{
		chMapSite = c_Panel->GetMapSiteOfSeat(i);
		if(chMapSite != 0)
		{
			if(c_itemName[chMapSite] != NULL)
				delete c_itemName[chMapSite] ;
			if(c_itemProtrait[chMapSite] != NULL)
				delete c_itemProtrait[chMapSite] ;
			c_itemName[chMapSite] = NULL;
			 c_itemProtrait[chMapSite] = NULL;
			uid = c_Panel->userIdOfSeat(i);
			puser = c_Panel->gameUser(uid,false);
			if(puser != NULL)
			{
				c_itemName[chMapSite] = new Q3CanvasText(puser->userName(),c_Canvas);
				c_itemName[chMapSite]->setColor(QColor(0,0,0xFF));
				f = c_itemName[chMapSite]->font();
				f.setPointSize(14);
				f.setBold(true);
				c_itemName[chMapSite]->setFont(f);
				if(c_bRequestDuce[chMapSite])
					pix = QPixmap(QString(":/LandBattleRes/image/pigeon.png"));
				else
					pix = puser->avatar();
        		img = pix.convertToImage();
        		img = img.smoothScale(64,64);
        		c_itemProtrait[chMapSite] = new LandBattleImageItem(img,c_Canvas,0,i,DESKTOP_IMAGE_TYPE_AVATOR);
				x = 0;y=0;
				GetAvatorPosition(chMapSite,c_itemProtrait[chMapSite],&x,&y);
				c_itemProtrait[chMapSite]->move(x,y);
				c_itemName[chMapSite]->move(x,y+65);
				c_itemName[chMapSite]->show();
				c_itemProtrait[chMapSite]->show();
			}
		}
	}
	c_Canvas->update();

}

void LandBattleDesktop::ClickSurrender()
{
	unsigned char buffer[200],chPathLen = 0;
	if(c_Panel->isLookingOn())
		return;
	GeneralGameTrace2Head *pmovet;
	JunqiTraceMove			*pmove;
	pmovet = (GeneralGameTrace2Head *)buffer;
	pmovet->chTable = c_Panel->c_Table;
	pmovet->chSite = c_Panel->c_Seat;
	pmovet->chType = JUNQI_GAMETRACE_MOVE;
	pmovet->chBufLen = sizeof(JunqiTraceMove);
	pmove = (JunqiTraceMove *)pmovet->chBuf;
	pmove->chMapSite = c_Panel->c_MapSite;
	pmove->chStartMapSite = 0;
	pmove->sxy = 0x0;
	
	QByteArray buf	= c_Panel->makeGameData( DJGAME_PROTOCOL_SUBTYPE_GAMETRACE2,QByteArray((char *)buffer,sizeof(GeneralGameTrace2Head)+pmovet->chBufLen) );
	DJClientRequest request( buf);
	c_Panel->sendRequest( request ,false);
}
void LandBattleDesktop::ClickDuce()
{
	unsigned char buffer[200],chPathLen = 0;
	if(c_Panel->isLookingOn())
		return;
	GeneralGameTrace2Head *pmovet;
	JunqiTraceMove			*pmove;
	pmovet = (GeneralGameTrace2Head *)buffer;
	pmovet->chTable = c_Panel->c_Table;
	pmovet->chSite = c_Panel->c_Seat;
	pmovet->chType = JUNQI_GAMETRACE_MOVE;
	pmovet->chBufLen = sizeof(JunqiTraceMove);
	pmove = (JunqiTraceMove *)pmovet->chBuf;
	pmove->chMapSite = c_Panel->c_MapSite;
	pmove->chStartMapSite = 0xFF;
	pmove->sxy = 0xFF;
	
	QByteArray buf	= c_Panel->makeGameData( DJGAME_PROTOCOL_SUBTYPE_GAMETRACE2,QByteArray((char *)buffer,sizeof(GeneralGameTrace2Head)+pmovet->chBufLen) );
	DJClientRequest request( buf);
	c_Panel->sendRequest( request ,false);
}
void LandBattleDesktop::gameWait( quint16 mask, quint8 status ,quint16 timeout)
{
	int x,y;
	unsigned char chMapSite = 0,chMask=1,i=1;
	while(i<=DJGAME_JUNQI_MAX_PLAYERS)
	{
		if(chMask & mask)
		{
			if( !(mask & (~chMask) ) )
			{
				chMapSite = c_Panel->GetMapSiteOfSeat(i);
			}
			break;
		}
		chMask <<= 1;
		i++;
	}
	GetTimerPosition(chMapSite,&x,&y);
	
	m_clockItem->move(x,y);
	m_clockItem->show( timeout );
}
/*
void LandBattleDesktop::SetTimerStatus(quint16 mask,int iTimeoutLine)
{
    int i;
	CreateTimer();
    if(iTimeoutLine == 0)
    {
     c_timer->stop();
     itemTimer->hide();
     itemTimerText->hide();
     return;
 	} else
        c_timer->start(1000,false);
	
	int iValue = iTimeoutLine-time(NULL);
    itemTimerText->setText(QString("%1").arg(iValue));
    c_shTimerMask = mask;

}
*/
/*
void LandBattleDesktop::CreateTimer()
{
	if(itemTimer == NULL)
	{
		itemTimer = new Q3CanvasSprite( c_paTimer,c_Canvas);
		itemTimer->hide();
		itemTimer->setFrameAnimation ( );
		itemTimer->setAnimated(TRUE);
		itemTimer->setZ(2000);
		
	}
	if(itemTimerText == NULL)
	{
		itemTimerText = new Q3CanvasText(c_Canvas);
		QFont f = itemTimerText->font();
		f.setBold(true);
		f.setPointSize (14);
		itemTimerText->setFont(f);
		itemTimerText->setColor(QColor(0,0,0xFF));
		itemTimerText->hide();
		itemTimerText->setZ(2000);
	}

}
*/
/*
void LandBattleDesktop::HandleTimeout()
{
	CreateTimer();
    if(c_Panel->c_iTimeoutLine-time(NULL) <= 1)
    {
        c_timer->stop();
        itemTimer->hide();
        itemTimerText->hide();
        return;
    }
    int iValue = c_Panel->c_iTimeoutLine-time(NULL);
    itemTimerText->setText(QString("%1").arg(iValue));
	int x,y;
	unsigned char chMapSite = 0,chMask=1,i=1;
	while(i<=DJGAME_JUNQI_MAX_PLAYERS)
	{
		if(chMask & c_shTimerMask)
		{
			if( !(c_shTimerMask & (~chMask) ) )
			{
				chMapSite = c_Panel->GetMapSiteOfSeat(i);
			}
			break;
		}
		chMask <<= 1;
		i++;
	}
	GetTimerPosition(chMapSite,&x,&y);

    itemTimer->move(x,y);
    itemTimerText->move(x+itemTimer->width()+1,y+16);
	itemTimer->show();
	itemTimerText->show();
}
*/
void LandBattleDesktop::GetAvatorPosition(quint8 chMapSite,LandBattleImageItem *item,int *x,int *y)
{
	PChessMapHead phead  = (PChessMapHead)GetChessmapHead(c_Panel->c_Chessmap);
		int chPlayers;
	int w,h;

	if(phead == NULL)
		chPlayers = c_Panel->GetCurrentPlayers();
	else
		chPlayers = phead->iContext;
	
	w = c_itemBoard->width();
	h = c_itemBoard->height();
	switch(chPlayers)
	{
		case 2 :	
		{
			if(chMapSite == c_Panel->c_MapSite)
			{
				*x = c_X-80;
				*y = c_Y+h-64;
			}else  if(chMapSite > 0 && chMapSite < 3)
			{
				*x = c_X+20+w;
				*y = c_Y;
			}
			break;
		}
		case 3 :
		{
			if(chMapSite == c_Panel->c_MapSite)
			{
				*x = c_X+90;
				*y = c_Y+h - 64;
			}else
			{
				unsigned char ch = c_Panel->c_MapSite+1;
				if(ch > 3)
					ch = 1;
				if(chMapSite == ch)
				{
					*x = c_X;
					*y = c_Y + 203;
				}else
				{
					ch ++;
					if(ch > 3)
						ch = 1;
					if(chMapSite == ch)
					{
						*y = c_Y+203;
						*x = c_X+w-64;
					}
				}
			}
			break;
		}
		case 4 :
		{
			if(chMapSite == c_Panel->c_MapSite)
			{//0
				*x = c_X+120;
				*y = c_Y+h - 64;
			}else
			{
				unsigned char ch = c_Panel->c_MapSite+1;
				if(ch > 4)
					ch = 1;
				if(chMapSite == ch)
				{//1
					*x = c_X;
					*y = c_Y + 100;
				}else
				{
					ch ++;
					if(ch > 4)
						ch = 1;
					if(chMapSite == ch)
					{//2
						*y = c_Y;
						*x = c_X+355;
					}else
					{
						ch ++;
						if(ch > 4)
							ch = 1;
						if(chMapSite == ch)
						{//3
							*y = c_Y+355;
							*x = c_X+w-64;
						}
					}
				}
			}
			break;
		}
	}
}

void LandBattleDesktop::GetTimerPosition(quint8 chMapSite,int *x,int *y)
{
	PChessMapHead phead  = (PChessMapHead)GetChessmapHead(c_Panel->c_Chessmap);
		int chPlayers;
	int w,h;

	if(phead == NULL)
		chPlayers = c_Panel->GetCurrentPlayers();
	else
		chPlayers = phead->iContext;
	
	w = c_itemBoard->width();
	h = c_itemBoard->height();
	switch(chPlayers)
	{
		case 2 :	
		{
			if(chMapSite == c_Panel->c_MapSite)
			{
				*x = c_X-80;
				*y = c_Y+h-97;
			}else  if(chMapSite > 0 && chMapSite < 3)
			{
				*x = c_X+20+w;
				*y = c_Y+80;
			}else
			{
				*x = c_X + (w >>1)-32;
				*y = c_Y +(h>>1)-16;
			}
			break;
		}
		case 3 :
		{
			if(chMapSite == c_Panel->c_MapSite)
			{
				*x = c_X+90;
				*y = c_Y+h - 97;
			}else
			{
				unsigned char ch = c_Panel->c_MapSite+1;
				if(ch > 3)
					ch = 1;
				if(chMapSite == ch)
				{
					*x = c_X;
					*y = c_Y + 170;
				}else
				{
					ch ++;
					if(ch > 3)
						ch = 1;
					if(chMapSite == ch)
					{
						*y = c_Y+170;
						*x = c_X+w-60;
					}else
					{
						*x = c_X + (w >>1)-32;
						*y = c_Y +(h>>1)-5;
					}
				}
			}
			break;
		}
		case 4 :
		{
			if(chMapSite == c_Panel->c_MapSite)
			{//0
				*x = c_X+120;
				*y = c_Y+h - 97;
			}else
			{
				unsigned char ch = c_Panel->c_MapSite+1;
				if(ch > 4)
					ch = 1;
				if(chMapSite == ch)
				{//1
					*x = c_X+65;
					*y = c_Y + 130;
				}else
				{
					ch ++;
					if(ch > 4)
						ch = 1;
					if(chMapSite == ch)
					{//2
						*y = c_Y+80;
						*x = c_X+355;
					}else
					{
						ch ++;
						if(ch > 4)
							ch = 1;
						if(chMapSite == ch)
						{//3
							*y = c_Y+355;
							*x = c_X+w-110;
						}else
						{//
							*x = c_X + (w >>1)-32;
							*y = c_Y +(h>>1)+32;
						}
					}
				}
			}
			break;
		}
	}
}


LandBattleDesktop::~LandBattleDesktop()
{
	if(!c_strSaveFile.isNull())
	{
		QFile file(c_strSaveFile);
		file.remove();
	}
	if(!c_strSaveLayoutFile.isNull())
	{
		QFile file(c_strSaveLayoutFile);
		file.remove();
	}
	delete m_clockItem;
	m_clockItem	= 0;
}

void LandBattleDesktop::ClickSave()
{
	unsigned char buffer[255];
	PGeneralGameTrace2Head ptrace = (PGeneralGameTrace2Head)buffer;
	
	 QDir dir = QDir::home();
    if (!dir.exists(QString("DJGameSave")))
	{
		 dir.mkdir("DJGameSave");
	}
	dir.cd("DJGameSave");
	if(c_Panel->c_chTableStatus == DJGAME_JUNQI_TABLE_STATUS_WAIT_ARRANGE)
	{
		memset(buffer,0,255);
		GetCurrentLayout(ptrace,c_Panel->c_MapSite);
		QString filename = QFileDialog::getSaveFileName(
                    this,
                    tr("Save the Layout"),
                    dir.path(),
                    tr("DJGame Save Files(*.sav)"));
		if(filename.isNull())
			return;
		if(!filename.endsWith(QString(".sav")) )
			filename += QString(".sav");
		InitSaveFileHead(c_Panel,filename,DJGAME_JUNQI,JUNQI_GAMETRACE_INITCHIP);
		AppendData2SaveFile(filename,(char *)buffer,sizeof(GeneralGameTrace2Head)+ptrace->chBufLen);
	}
}

void LandBattleDesktop::PlayerMoveChip( const GeneralGameTrace2Head *gameTrace )
{
	PJunqiTraceMove pmove = (PJunqiTraceMove)gameTrace->chBuf;
	PMapNode 	pstart,pend;
	NODEID id;
	if(c_PlayerMoveNodeStart != NULL && c_PlayerMoveNodeEnd != NULL)
		HandleMoveTimeout();
	
	if(pmove->chStartMapSite == 0 && pmove->sxy == 0)
		return;
	
	if(pmove->chStartMapSite == 0xFF && pmove->sxy == 0xFF)
	{//求和
		c_bRequestDuce[pmove->chMapSite] = true;
		RepaintPlayer();
		return;
	}
	id.district  = 0;
	id.id = GET_NODEID(pmove->chStartMapSite,0,pmove->sxy);
	pstart = SearchNode(c_Panel->c_Chessmap,&id);
	if(pstart != NULL)
	{
		CHIPPOWER power;
		power.power = JUNQI_MAX_POWER;
		DEBUG_OUTPUT(("Move : "));
		DEBUG_BUFFER(((char *)pmove,gameTrace->chBufLen));
		pend = CheckPath(c_Panel->c_Chessmap,&power,pstart,pmove->path);
		if(pstart->chip.id == 0 || pend == NULL)
		{
			DEBUG_OUTPUT(("Move Error ! "));
		//	QMessageBox::information(c_Panel,tr("Error!"),tr("Local data error. Please quit game and login again."),QMessageBox::Ok);
			return;
		}
		
		if(pend != NULL)
		{
			ClearNodeChip(pstart);
			CreateNodeChip(pstart,true);
			DrawPath(pstart,pmove->path);
			c_PlayerMoveNodeStart = pstart;
			c_PlayerMoveNodeEnd   = pend;
			c_MoveResult = pmove->chResult;
			c_MoveTimer->start(1000);
		}
		
	}
	
}

void LandBattleDesktop::DrawPath(PMapNode pcurnode,unsigned char *path)
{
	bool bHigh =false;
	unsigned char pin;
	PMapNode plastnode = pcurnode,pnextnode = NULL;
	
	while(pcurnode != NULL)
	{
		if(bHigh)
		{
			pin = (*path)>>4;
		}else
			pin =(*path) & 0x0F;
		if(pin == 0 || pin > DJGAME_CHESSMAP_MAX_PINS)
			break;
		pnextnode = pcurnode->pin[pin].pnode;
		if(pnextnode != NULL)
		{
			Q3CanvasLine *item = new Q3CanvasLine(c_Canvas);
			item->setPoints(pcurnode->x+c_X,pcurnode->y+c_Y,pnextnode->x+c_X,pnextnode->y+c_Y);
			item->setPen(QPen(QColor(255,0,0),3));
			item->setZ(2000);
			item->show();
		}
		plastnode = pcurnode;
		pcurnode = pnextnode;
		if(!bHigh)
			path ++;
		bHigh =!bHigh;
	}
			
}

void LandBattleDesktop::HandleMoveTimeout()
{
	c_MoveTimer->stop();
	switch(c_MoveResult)
	{
		case JUNQI_MOVERESULT_SET :
			if(c_Panel->c_LastTraceType == 0)
			{
				if(c_PlayerMoveNodeEnd->chip.id != 0)
					c_Panel->playWave("kill.wav");
				else
					c_Panel->playWave("move.wav");
			}
			memcpy(&c_PlayerMoveNodeEnd->chip,&c_PlayerMoveNodeStart->chip,sizeof(CHIP));
			break;
		case JUNQI_MOVERESULT_CLEAR :
			if(c_Panel->c_LastTraceType == 0)
				c_Panel->playWave("dkill.wav");
			memset(&c_PlayerMoveNodeEnd->chip,0,sizeof(CHIP));
			break;
	}
	
	
	
	ClearAllLine();

	ClearNodeChip(c_PlayerMoveNodeEnd);
	CreateNodeChip(c_PlayerMoveNodeEnd);
	memset(&c_PlayerMoveNodeStart->chip,0,sizeof(CHIP));
		ClearNodeChip(c_PlayerMoveNodeStart);
		CreateNodeChip(c_PlayerMoveNodeStart);		
	c_PlayerMoveNodeStart = NULL;
	c_PlayerMoveNodeEnd = NULL;
}

void LandBattleDesktop::ClearAllLine()
{
	Q3CanvasItemList list = c_Canvas->allItems();
    Q3CanvasItemList::Iterator it = list.begin();
    for (; it != list.end(); ++it)
    {
        if ( *it && (*(it))->rtti() == Q3CanvasItem::Rtti_Line )
            delete *it;
    }
}
void LandBattleDesktop::ClickSend()
{
	unsigned char buffer[255];
	PGeneralGameTrace2Head ptrace = (PGeneralGameTrace2Head)buffer;
	PJunqiTraceInitChip    pcurchips = (PJunqiTraceInitChip)ptrace->chBuf;
	
	if(c_Panel->c_chTableStatus == DJGAME_JUNQI_TABLE_STATUS_WAIT_ARRANGE && c_bArrange && !c_bWaitACL)
	{
		GetCurrentLayout(ptrace,c_Panel->c_MapSite);
		if(JunqiCheckArrange(pcurchips,pcurchips))
		{
			c_bWaitACL = true;
			QByteArray buf	= c_Panel->makeGameData( DJGAME_PROTOCOL_SUBTYPE_GAMETRACE2,QByteArray((char *)buffer,sizeof(GeneralGameTrace2Head)+ptrace->chBufLen) );
			QVariant parameters	= QVariant::fromValue((void*)this);
			DJClientRequest request( buf ,HandleArrangeACL,parameters);
			c_Panel->sendRequest( request ,false);
		
		}else
		{
			QMessageBox::information( c_Panel,tr("Layout Error"),tr("This is a invalid layout."),QMessageBox::Ok);
		}
	}
}

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


void  HandleArrangeACL( const QByteArray& buf, const QVariant& parameters )
{
    PDJGameProtocol pacl = (PDJGameProtocol)buf.data();
    LandBattleDesktop* desktop = static_cast<LandBattleDesktop *>(parameters.value<void*>());
        
	desktop->c_bWaitACL = false;
    if(buf.size() == 0)
    {
        return ;
    }
    if( DJGAME_SUCCESS(pacl->chBuf[0]) )
	{
		desktop->c_bArrange = false;
	}
}
	
void LandBattleDesktop::ClickLoad()
{
	unsigned char buffer[255];
	unsigned char *savbuf;
	PGeneralGameTrace2Head ptrace = (PGeneralGameTrace2Head)buffer;
	PGeneralGameTrace2Head psavet;
	PJunqiTraceInitChip    pcurchips = (PJunqiTraceInitChip)ptrace->chBuf;
	PJunqiTraceInitChip	   psavchips;
	
	 QDir dir = QDir::home();
    if (!dir.exists(QString("DJGameSave")))
	{
		 dir.mkdir("DJGameSave");
	}
	dir.cd("DJGameSave");
	if(c_Panel->c_chTableStatus == DJGAME_JUNQI_TABLE_STATUS_WAIT_ARRANGE)
	{
		memset(buffer,0,255);
		GetCurrentLayout(ptrace,c_Panel->c_MapSite);
		QString filename = QFileDialog::getOpenFileName(
                    this,
                    tr("Load Layout"),
                    dir.path(),
                    tr("DJGame Save Files(*.sav)"));
		if(filename.isNull())
			return;
		unsigned int shLen;
		savbuf = (unsigned char *)GetSaveData(filename,DJGAME_JUNQI,JUNQI_GAMETRACE_INITCHIP,&shLen);
		if(savbuf == NULL)
		{
			QMessageBox::information( c_Panel,tr("Layout File Error"),tr("It isn't a DJGame save-file."),QMessageBox::Ok);
			return;
		}
		psavet = (PGeneralGameTrace2Head)savbuf;
		psavchips = (PJunqiTraceInitChip)psavet->chBuf;
		//DEBUG_OUTPUT(("Load Saved Layout\n"));
		//	JUNQI_DEBUG_OUTPUT_ARRANGE((psavet));
		DEBUG_BUFFER(((char *)psavet,shLen));
		if(psavchips->chChips == pcurchips->chChips)
		{
			psavchips->chMapSite = c_Panel->c_MapSite;
			int i;
			for(i=0;i<=psavchips->chChips;i++)
			{
				psavchips->chip[i].chip.owner = c_Panel->c_MapSite;
			}
			DEBUG_OUTPUT(("Load Saved Layout\n"));
			JUNQI_DEBUG_OUTPUT_ARRANGE((psavet));
		}
			
		if(psavchips->chChips != pcurchips->chChips || !JunqiCheckArrange( pcurchips,psavchips ) )
		{
			QMessageBox::information( c_Panel,tr("Layout File Error"),tr("It is a layout file but cant match here."),QMessageBox::Ok);
			return;
		}
		Initchip(psavchips);
		
	}
}

void LandBattleDesktop::HandleExchangeTimeout()
{
	if(c_pArrangeNode1 == NULL || c_pArrangeNode2 == NULL)
		return;
	CHIP tmp;
	memcpy(&tmp,&(c_pArrangeNode1->chip),sizeof(CHIP));
	memcpy(&(c_pArrangeNode1->chip),&(c_pArrangeNode2->chip),sizeof(CHIP));
	memcpy(&(c_pArrangeNode2->chip),&tmp,sizeof(CHIP));

	ClearNodeChip(c_pArrangeNode1);
	ClearNodeChip(c_pArrangeNode2);
	c_Canvas->update();
	c_Panel->playWave("move.wav");
	CreateNodeChip(c_pArrangeNode1);
	CreateNodeChip(c_pArrangeNode2);
	c_pArrangeNode1 = NULL;
	c_pArrangeNode2 = NULL;
}
void LandBattleDesktop::contentsDragMoveEvent ( QDragMoveEvent * e )
{
	if(c_Panel->c_chTableStatus == DJGAME_JUNQI_TABLE_STATUS_WAIT_MOVE && c_Panel->WaittingForMe() && c_bMove && !c_bWaitACL && c_pMoveChipNode != NULL)
	{
		QPoint pp = inverseWorldMatrix().map(e->pos());
		PMapNode pnode = GetNodeByPoint(pp.x(),pp.y());
		if(pnode != NULL && pnode != c_pMoveTempEnd)
		{
			ClearAllLine();
			unsigned char *p;
			if(MoveChip(c_Panel->c_Chessmap,GET_BoardOfNode( (&(c_pMoveChipNode->id))),c_pMoveChipNode->id.id & 0xFF,
								GET_BoardOfNode( (&(pnode->id))),pnode->id.id & 0xFF,&p) )
			{
				DrawPath(c_pMoveChipNode,p);
			}
			c_pMoveTempEnd = pnode;
		}
	}
}
void LandBattleDesktop::contentsMouseReleaseEvent(QMouseEvent* e)
{
	LandBattleImageItem *item;
	PMapNode 	pnode;
	
	if(c_Panel->isLookingOn())
		return;

	QPoint pp = inverseWorldMatrix().map(e->pos());
//	if (e->button() == Qt::LeftButton) 
	{
		pnode = GetNodeByPoint(pp.x(),pp.y());
		if(c_Panel->c_chTableStatus == DJGAME_JUNQI_TABLE_STATUS_WAIT_ARRANGE && c_bArrange)
		{
			if(c_pArrangeNode1 != NULL && c_pArrangeNode2 != NULL)
				return;
			if( e->button() == Qt::RightButton || pnode == NULL)
			{
				item = GetChipOfNode(c_pArrangeNode1);
				if(item != NULL)
					item->SetImageMark(false);
				item = GetChipOfNode(c_pArrangeNode2);
				if(item != NULL)
					item->SetImageMark(false);
				c_pArrangeNode1 = NULL;
				c_pArrangeNode2 = NULL;
				c_Canvas->update();
				return;
			}
			if(pnode == NULL || GET_BoardOfNode((&pnode->id)) != c_Panel->c_MapSite)
				return;
			if(c_pArrangeNode1 == NULL)
			{
				item = GetChipOfNode(pnode);
				if(item != NULL)
					item->SetImageMark(true);
				c_pArrangeNode1 = pnode;
				c_Canvas->update();
				c_Panel->playWave("click.wav");
				return;
			}else 
			{
				item = GetChipOfNode(pnode);
				if(item != NULL)
					item->SetImageMark(true);
				c_pArrangeNode2 = pnode;
				c_Canvas->update();
				c_Panel->playWave("click.wav");
				c_timerExchange->start(1000);
				return;
			}
		}else if(c_Panel->c_chTableStatus == DJGAME_JUNQI_TABLE_STATUS_WAIT_MOVE && c_Panel->WaittingForMe() && c_bMove && !c_bWaitACL)
		{
			if(pnode == NULL || pnode == c_pMoveChipNode)
			{
				if(c_pMoveChipNode != NULL)
				{
					item = GetChipOfNode(c_pMoveChipNode);
					if(item != NULL)
						item->SetImageMark(false);
					c_pMoveChipNode = NULL;
				}
				return;
			}
			item = GetChipOfNode(pnode);
			if(c_pMoveChipNode == NULL || (pnode->chip.id != 0 && pnode->chip.owner == c_Panel->c_MapSite ) )
			{
				if(c_pMoveChipNode != NULL && pnode->chip.id != 0 && pnode->chip.owner == c_Panel->c_MapSite)
				{
					LandBattleImageItem *item2 = GetChipOfNode(c_pMoveChipNode);
					if(item2 != NULL)
						item2->SetImageMark(false);
					c_pMoveChipNode = NULL;
				}
				if(pnode->chip.id != 0 && pnode->chip.owner == c_Panel->c_MapSite)
				{
					c_pMoveChipNode = pnode;
					if(item != NULL)
						item->SetImageMark(true);
				}
				return;
			}
			
			if( pnode->chip.id == 0 || !IsFriendlyPlayer(c_Panel->c_chUnion,c_Panel->c_chUnions,pnode->chip.owner,c_pMoveChipNode->chip.owner) )
			{//Move
				unsigned char *p;
				if(MoveChip(c_Panel->c_Chessmap,GET_BoardOfNode( (&(c_pMoveChipNode->id))),c_pMoveChipNode->id.id & 0xFF,
								GET_BoardOfNode( (&(pnode->id))),pnode->id.id & 0xFF,&p) )
				{
					DEBUG_OUTPUT(("Move OK\n"));
					unsigned char buffer[200],chPathLen = 0;
					GeneralGameTrace2Head *pmovet;
					JunqiTraceMove			*pmove;
					pmovet = (GeneralGameTrace2Head *)buffer;
					pmovet->chTable = c_Panel->c_Table;
					pmovet->chSite = c_Panel->c_Seat;
					pmovet->chType = JUNQI_GAMETRACE_MOVE;
					pmovet->chBufLen = sizeof(JunqiTraceMove);
					pmove = (JunqiTraceMove *)pmovet->chBuf;
					pmove->chMapSite = c_Panel->c_MapSite;
					pmove->chStartMapSite = GET_BoardOfNode( (&(c_pMoveChipNode->id)));
					pmove->sxy = c_pMoveChipNode->id.id & 0xFF;
					while(*p != 0)
					{
						pmove->path[chPathLen] = *p;
						p++;
						chPathLen ++;
					}
					pmove->path[chPathLen] = 0;
					pmove->path[chPathLen+1] = 0;
					pmovet->chBufLen += chPathLen;
					DEBUG_OUTPUT(("Request Move : "));
					DEBUG_BUFFER(((char *)pmove,pmovet->chBufLen));
					c_bWaitACL = true;
					QByteArray buf	= c_Panel->makeGameData( DJGAME_PROTOCOL_SUBTYPE_GAMETRACE2,QByteArray((char *)buffer,sizeof(GeneralGameTrace2Head)+pmovet->chBufLen) );
					QVariant parameters	= QVariant::fromValue((void*)this);
					DJClientRequest request( buf ,HandleMoveACL,parameters);
					
					LandBattleImageItem *item2 = GetChipOfNode(c_pMoveChipNode);
					if(item2 != NULL)
						item2->SetImageMark(false);
					c_pMoveChipNode = NULL;
					
					c_Panel->sendRequest( request ,false);
					
				}else
				{
					DEBUG_OUTPUT(("Move false\n"));;
				}
				
				return;
			}
		}
	}
}

void LandBattleDesktop::GetCurrentLayout(PGeneralGameTrace2Head ptrace,unsigned char chMapSite)
{
	NODEID id;
	int i,j,k = 0;
	PJunqiTraceInitChip	psetchips = (PJunqiTraceInitChip)ptrace->chBuf;
	
	PMapNode pnode;
	id.district = 0;
	for(i=1;i<=6;i++)
	{
		for(j=1;j<=5;j++)
		{
			id.id = GET_NODEID(chMapSite,i,j);
			pnode = SearchNode(c_Panel->c_Chessmap,&id);
			if(pnode != NULL && pnode->chip.id != 0)
			{
				psetchips->chip[k].xy = (unsigned char)(id.id & 0xFF);
				psetchips->chip[k].chip.id = (unsigned char)(pnode->chip.id);
				psetchips->chip[k].chip.owner = chMapSite;
				psetchips->chip[k].chip.power = (unsigned char )(pnode->chip.power.power);
				k++;
			}
		}
	}
	ptrace->chTable = c_Panel->c_Table;
	ptrace->chSite  = c_Panel->GetSeatOfMapSite(chMapSite);
	ptrace->chType  = JUNQI_GAMETRACE_INITCHIP;
	ptrace->chBufLen = k*sizeof(JunqiTraceChip) + sizeof(JunqiTraceInitChip);
	psetchips->chMapSite = chMapSite;
	psetchips->chChips = k;
	DEBUG_OUTPUT(("GetCurrentLayout : \n"));
	JUNQI_DEBUG_OUTPUT_ARRANGE((ptrace));
	
}

PMapNode LandBattleDesktop::GetNodeByPoint(int x,int y)
{
	LandBattleImageItem *item;
	QPoint p(x,y);
	Q3CanvasItemList l=canvas()->collisions(p);
	Q3CanvasItemList::Iterator it=l.begin();
	while(it != l.end())
	{
		if((*it)->rtti() == imageRTTI )
		{
			item = (LandBattleImageItem *)(*it);
			if(item->c_chType == DESKTOP_IMAGE_TYPE_CHIP)
			{
				NODEID		id;
				id.district = 0;
				id.id = item->c_chSeat;
				return SearchNode(c_Panel->c_Chessmap,&id);
			}
		}
		it ++;
	}
	return Point2Node(c_Panel->c_Chessmap,x-c_X,y-c_Y,JUNQI_CHESSMAP_RANGE,JUNQI_CHESSMAP_RANGE);
}
LandBattleImageItem * LandBattleDesktop::GetChipOfNode(PMapNode pnode)
{
	int x,y;
	LandBattleImageItem *item;
	if(pnode == NULL)
		return NULL;
	x = pnode->x+c_X;
	y = pnode->y+c_Y;
	QPoint p(x,y);

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

void LandBattleDesktop::WaitStart()
{
	c_pbStart->show();
	c_pbSave->hide();
	c_pbSend->hide();
	c_pbLoad->hide();
	
	c_pbSurrender->hide();
	c_pbDuce->hide();
	int i;
	for(i=0;i<8;i++)
		c_bRequestDuce[i] = false;
}

void LandBattleDesktop::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 );

	if(c_strSaveFile.isEmpty())
		c_strSaveFile = GetTempSaveFileName(DJGAME_JUNQI);
	if(c_strSaveLayoutFile.isEmpty())
		c_strSaveLayoutFile = GetTempSaveFileName(DJGAME_JUNQI,1);
	InitSaveFileHead(c_Panel,c_strSaveFile,DJGAME_JUNQI,JUNQI_GAMETRACE_MOVE);
	InitSaveFileHead(c_Panel,c_strSaveLayoutFile,DJGAME_JUNQI,JUNQI_GAMETRACE_SHOWARRANGE);
}
bool LandBattleDesktop::hasStarted()
{
	return !c_pbStart->isVisible();
}
void LandBattleDesktop::WaitMove(bool bIncludeMe)
{
	c_pMoveChipNode = NULL;
	if(bIncludeMe && !c_Panel->isLookingOn())
	{
		c_pbSurrender->show();
		if(!c_bRequestDuce[c_Panel->c_MapSite] )
			c_pbDuce->show();
		else 
			c_pbDuce->hide();
		c_bMove = true;
	}else
	{
		c_pbSurrender->hide();
		c_pbDuce->hide();
		c_bMove = false;
	}
	c_bWaitACL = false;
	
	
}

void LandBattleDesktop::WaitArrange(bool bIncludeMe)
{
	c_bArrange = bIncludeMe;
	if(c_bArrange && !c_Panel->isLookingOn())
	{
		c_pbSave->setText(tr("Save Layout"));
		c_pbSend->setText(tr("Go Out!"));
		int x,y;
		y = c_Y+c_itemBoard->height()-120;
		PChessMapHead phead  = (PChessMapHead)GetChessmapHead(c_Panel->c_Chessmap);
		switch(phead->iContext)
		{
			case 2 :
				x = c_X+c_itemBoard->width()+50;
				break;
			case 3 :
				x = c_X+360;
				break;
			case 4 :
				x = c_X+420;
				break;
			default :
				return;				
		}
		
		//c_pbLoad->setGeometry(x,y,100,24);
		//c_pbSave->setGeometry(x,y+30,100,24);
		//c_pbSend->setGeometry(x,y+60,100,24);
		c_pbLoad->move(x,y);
		c_pbSave->move(x,y+30);
		c_pbSend->move(x,y+60);
		c_pbSave->show();
		c_pbLoad->show();
		c_pbSend->show();
	}else
	{
		c_pbLoad->hide();
		c_pbSave->hide();
		c_pbSend->hide();
	}
	
}

void LandBattleDesktop::SetPlayerChip(PJunqiSetChip psetchip)
{
	SetChip(c_Panel->c_Chessmap,psetchip->chMapSite,psetchip->chip.xy,&(psetchip->chip.chip));
	
	c_Panel->playWave("move.wav");
	PMapNode pnode;
	NODEID nodeid;
	nodeid.district = 0;
	nodeid.id = GET_NODEID(psetchip->chMapSite,0,psetchip->chip.xy);
	pnode =SearchNode(c_Panel->c_Chessmap,&nodeid);
	if(pnode != NULL)
	{
		ClearNodeChip(pnode);
		CreateNodeChip(pnode);
	}
}

void LandBattleDesktop::Initchip(PJunqiTraceInitChip psetchips)
{
	int i,j;
	
	PMapNode pnode;
	NODEID	nodeid;
	
	nodeid.district = 0;
	for(i=1;i<=6;i++)
	{
		for(j=1;j<=5;j++)
		{
			nodeid.id = GET_NODEID(psetchips->chMapSite,i,j);
			pnode = SearchNode(c_Panel->c_Chessmap,&nodeid);
			if(pnode != NULL)
			{
				memset(&(pnode->chip),0,sizeof(CHIP));
				ClearNodeChip(pnode);
			}
		}
	}
	for(i=0;i<psetchips->chChips;i++)
	{
		SetChip(c_Panel->c_Chessmap,psetchips->chMapSite,psetchips->chip[i].xy,&(psetchips->chip[i].chip));
		nodeid.id = GET_NODEID(psetchips->chMapSite,0,psetchips->chip[i].xy);
		pnode = SearchNode(c_Panel->c_Chessmap,&nodeid);
		if(pnode != NULL)
		{
			DEBUG_OUTPUT(("chip%d nodeid=%04x chipid=%d chipower=%d chipowner=%d x=%d y=%d\n",i,pnode->id.id,pnode->chip.id,pnode->chip.power.power,pnode->chip.owner,pnode->x,pnode->y));
			CreateNodeChip(pnode);
		}
	}
	c_Canvas->update();

}

void LandBattleDesktop::CreateNodeChip(PMapNode pnode,bool bBig)
{
	int iIndex;
	char chBoard;
	if(pnode == NULL)
		return;
	if(pnode->chip.id == 0 || pnode->chip.owner == 0)
		return;
	if(pnode->chip.id == DJGAME_JUNQI_RANK_WEIZHI)
		iIndex = 0;
	else
	{
		iIndex = pnode->chip.id;
	}
	PChessMapHead phead  = (PChessMapHead)GetChessmapHead(c_Panel->c_Chessmap);
	iIndex = iIndex*4+pnode->chip.owner;
	chBoard = GetPhysicalBoard(pnode);
	
	char szName[255];
	sprintf(szName,":/LandBattleRes/image/jqchip%d_%02d.png",chBoard,iIndex);
	DEBUG_OUTPUT((szName));
	DEBUG_OUTPUT(("\n"));
	QPixmap pix = QPixmap(QString(szName));
	Q3CanvasPolygonalItem *item;
	QImage img;
	if(!pix.isNull())
	{
		img = pix.convertToImage(); 
		if(bBig)
			img = img.smoothScale(pix.width()+5,pix.height()+5);			
		item = new LandBattleImageItem(img,c_Canvas,0,pnode->id.id,DESKTOP_IMAGE_TYPE_CHIP);
		int x,y;
		x = pnode->x+c_X - (img.width()>>1);
		y = pnode->y+c_Y - (img.height()>>1);
		item->move(x,y);
		item->show();
		if(iIndex == 0)
			item->setZ(1000);
		else
			item->setZ(500);
	}
	
}

char LandBattleDesktop::GetPhysicalBoard(PMapNode pnode)
{
	PChessMapHead phead  = (PChessMapHead)GetChessmapHead(c_Panel->c_Chessmap);
	if(phead->iContext == 2)
		return 1;
	
	char iBoard = GET_BoardOfNode(&(pnode->id));
	if(iBoard == DJGAME_JUNQI_CONNECTER_AREA)
		return 1;
	if(phead->iContext == 4)
	{
		if(iBoard%2 == c_Panel->c_MapSite%2)
			return 1;
		return 4;
	}
	if(phead->iContext == 3)
	{
		if(iBoard == c_Panel->c_MapSite)
			return 1;
		
		unsigned char chCur = c_Panel->c_MapSite,chRet=1;
		do
		{
			chCur ++;
			chRet ++;
			if(chCur > 3)
				chCur = 1;
		}while(chCur != iBoard);
		
		return chRet;
	}
	return 1;
}

void LandBattleDesktop::ClearNodeChip(PMapNode pnode)
{
	LandBattleImageItem *item = GetChipOfNode(pnode);
	if(item != NULL)
	{
		delete item;
	}
	
}

void LandBattleDesktop::RepaintChessmap(int iContext)
{
	if(c_itemBoard != NULL)
	{
		delete c_itemBoard;
		c_itemBoard = NULL;
	}
	QPixmap pix;
	switch(iContext)
	{
		case 2 :
			pix = QPixmap(QString(":/LandBattleRes/image/jq2board.png"));
			break;
		case 3 :
			pix = QPixmap(QString(":/LandBattleRes/image/jq3board.png"));
			break;
		case 4 :
			pix = QPixmap(QString(":/LandBattleRes/image/jq4board.png"));
			break;
		default :
			return;
	}
	c_X = (c_Canvas->width()-pix.width())>>1;
	c_Y = (c_Canvas->height()-pix.height())>>1;
	QImage img = pix.convertToImage();
	c_itemBoard = new LandBattleImageItem(img,c_Canvas,0,0,DESKTOP_IMAGE_TYPE_BOARD);
	c_itemBoard->move(c_X,c_Y);
	c_itemBoard->show();
	c_itemBoard->setZ(100);
	c_Canvas->update();
}
void LandBattleDesktop::resizeEvent( QResizeEvent * )
{	
	int w,h;
	w = width()-5;
	h = height()-5;
	if(w < 540)
		w = 540;
	if(h < 540)
		h = 540;
	
	c_Canvas->resize(w,h);
	
	QPixmap pix(2,h+10);
	QRect rect = pix.rect();
	QPainter p(&pix);
	QLinearGradient linearGradient( rect.topLeft(), rect.bottomLeft() );
	
   	linearGradient.setColorAt(0, QColor(75,130,170));
	linearGradient.setColorAt(0.5, QColor(97,148,185));
	linearGradient.setColorAt(1, QColor(75,130,170));
	p.fillRect( rect, linearGradient );
	p.end();
	c_Canvas->setBackgroundPixmap(pix);
	QPalette pal = palette();
	pal.setBrush(QPalette::Background,linearGradient);
	setPalette(pal);
	
	//c_pbStart->setGeometry( (width()-64)>>1,(height()>>1)+80,80,30);
	//c_pbSurrender->setGeometry(width()-180,height()-90,120,30);
	//c_pbDuce->setGeometry(width()-180,height()-60,120,30);
	c_pbStart->move( (width()-c_pbStart->width())>>1,(height()>>1)+80);
	c_pbSurrender->move(width()-c_pbSurrender->width(),height()-90);
	c_pbDuce->move(width()-c_pbDuce->width(),height()-60);
	if(c_itemBoard != NULL)
	{
		int i,j,k;
		NODEID id;
		PMapNode pnode;
		id.district = 0;
		ClearAllChips();
		c_X = (c_Canvas->width()-c_itemBoard->width())>>1;
		c_Y = (c_Canvas->height()-c_itemBoard->height())>>1;		
		c_itemBoard->move(c_X,c_Y);
		for(i=1;i<=DJGAME_JUNQI_MAX_PLAYERS;i++)
		{
			for(j=1;j<=6;j++)
			{
				for(k=1;k<=5;k++)
				{
					id.id = GET_NODEID(i,j,k);
					pnode = SearchNode(c_Panel->c_Chessmap,&id);
					CreateNodeChip(pnode);
				}
			}
		}
	}
	c_Canvas->update();
}

void LandBattleDesktop::ClearAllChips()
{
    Q3CanvasItemList list = c_Canvas->allItems();
    Q3CanvasItemList::Iterator it = list.begin();
	LandBattleImageItem *item;
    while(it != list.end())
    {
    	if((*it)->rtti() == imageRTTI )
		{
			item = (LandBattleImageItem *)(*it);
			
        	if ( item->c_chType == DESKTOP_IMAGE_TYPE_CHIP )
           	 	delete item;
        }
        it++;
    }
}
//////////////////////////////////////////////////////

LandBattlePanel::LandBattlePanel( 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 )
{
	c_Table = tableId;
	c_Seat  = seatId;
	c_Ctrl	= gameController;
	c_Room	= room;
	
	//char chDbgFile[60];
	
	Init4CountryChessmap(c_Chessmap,LANDBATTLEPANEL_CHESSMAP_MAXSIZE,c_MapSite);
	
	//sprintf(chDbgFile,"Junqi_%d_%d.dbg",tableId,seatId);
	//DEBUG_INITFILE((chDbgFile));
	QSplitter* mainSplitter = new QSplitter(Qt::Horizontal , this);
	setCentralWidget( mainSplitter );
	QSplitter *leftSplitter		= new QSplitter(Qt::Vertical , mainSplitter);
	QSplitter *rightSplitter	= new QSplitter(Qt::Vertical , mainSplitter);
	
	setAccessorySplitter( leftSplitter );
	
	c_Ad = new DJTopWidget(rightSplitter);
	
	c_DesktopCanvas = new  Q3Canvas(this);
	c_DesktopCanvas->resize(100,100);
	c_Desktop = new LandBattleDesktop(c_DesktopCanvas,rightSplitter,this);
	
	memset(&c_Current,0,sizeof(JunqiCurrent));
	
	c_chUnions = 0;
	memset(c_chUnion,0,5);
	
	c_chTableStatus	= 0;
	c_MapSite	= 0;
	c_LastTraceType	= 0;
	c_shWaitMask	= 0;
	c_iTimeoutLine	= 0;
}
void LandBattlePanel::createAccessoryWidgets()
{
	QSplitter	*splitter	= accessorySplitter();
	if ( splitter ) {
		createPlayersWidget( splitter );
		createChatWidget( splitter );
	}
}
unsigned char LandBattlePanel::GetCurrentPlayers()
{
	unsigned char i,players = 0;
	for(i=1;i<=DJGAME_JUNQI_MAX_PLAYERS;i++)
	{
		if(userIdOfSeat(i) != 0)
			players++;
	}
	return players;
}
LandBattlePanel::~LandBattlePanel()
{
}
/*
void LandBattlePanel::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 LandBattlePanel::userArrived( quint32 userId, quint8 seatId )
{
	DJGamePanel::userArrived( userId, seatId );
	c_Desktop->RepaintPlayer();
}

unsigned char LandBattlePanel::GetSeatOfMapSite(unsigned char chMapSite)
{
	return c_Current.chMapSites[chMapSite];
}
unsigned char LandBattlePanel::GetMapSiteOfSeat(unsigned char seat)
{
	int i = 1;
	while(i<=DJGAME_JUNQI_MAX_PLAYERS)
	{
		if(c_Current.chMapSites[i] == seat)
			return i;
		i++;
	}
	return 0;
}

void LandBattlePanel::gameInfo( const unsigned char *buf )
{
	//qDebug() << "LandBattlePanel::gameInfo";
	PJunqiCurrent pcurrent =(PJunqiCurrent)buf;
	memcpy(&c_Current,buf,sizeof(JunqiCurrent));
	memset(c_Chessmap,0,LANDBATTLEPANEL_CHESSMAP_MAXSIZE);
	c_MapSite = GetMapSiteOfSeat(c_Seat);
	
	switch(pcurrent->chMapID)
	{
		case JUNQI_MAP_NORMAL2 :
			DEBUG_OUTPUT(("JUNQI_MAP_NORMAL2\n"));
			Init2CountryChessmap(c_Chessmap,LANDBATTLEPANEL_CHESSMAP_MAXSIZE,c_MapSite);
			break;
		case JUNQI_MAP_NORMAL3 :
			DEBUG_OUTPUT(("JUNQI_MAP_NORMAL3\n"));
			Init3CountryChessmap(c_Chessmap,LANDBATTLEPANEL_CHESSMAP_MAXSIZE,c_MapSite);
			break;
		case JUNQI_MAP_NORMAL4 : 
			DEBUG_OUTPUT(("JUNQI_MAP_NORMAL4\n"));
			Init4CountryChessmap(c_Chessmap,LANDBATTLEPANEL_CHESSMAP_MAXSIZE,c_MapSite);
			break;
		case JUNQI_MAP_4ROW :
			break;
	}
//	DEBUG_BUFFER((c_Chessmap,BufferGetAllocTotalSize(c_Chessmap)));
	c_Desktop->RepaintChessmap(pcurrent->chMapID);
	c_Desktop->RepaintPlayer();
	//qDebug() << "LandBattlePanel::gameInfo end";
}

bool LandBattlePanel::WaittingForMe()
{
	if(c_chTableStatus != DJGAME_TABLE_STATUS_WAITSTART &&
			c_chTableStatus != DJGAME_JUNQI_TABLE_STATUS_WAIT_ARRANGE &&
			c_chTableStatus != DJGAME_JUNQI_TABLE_STATUS_WAIT_MOVE )
		return false;
	quint16 shMyMask = 1<<(c_Seat-1);
	return (shMyMask & c_shWaitMask);
}

void LandBattlePanel::gameWait( quint16 mask, quint8 status ,quint16 timeout )
{
	c_iTimeoutLine = time(NULL)+timeout;
    c_chTableStatus = status;
	c_shWaitMask = mask;
	
	quint16 shMyMask = 1<<(c_Seat-1);
	
	//c_Desktop->SetTimerStatus(mask,c_iTimeoutLine);
	c_Desktop->gameWait( mask, status, timeout );
	
	c_LastTraceType = 0;
	if(shMyMask & mask)
	{
		switch(c_chTableStatus)
        {
        	case DJGAME_TABLE_STATUS_WAITSTART :
				c_Desktop->WaitStart();
				break;
			case DJGAME_JUNQI_TABLE_STATUS_WAIT_ARRANGE :
				c_Desktop->WaitArrange(true);
				break;
			case DJGAME_JUNQI_TABLE_STATUS_WAIT_MOVE :
				c_Desktop->WaitArrange(false);
				c_Desktop->WaitMove(true);
				break;
		}
	}else
	{
		switch(c_chTableStatus)
        {
        	case DJGAME_TABLE_STATUS_WAITSTART :
				break;
			case DJGAME_JUNQI_TABLE_STATUS_WAIT_ARRANGE :
				c_Desktop->WaitArrange(false);
				break;
			case DJGAME_JUNQI_TABLE_STATUS_WAIT_MOVE :
				c_Desktop->WaitArrange(false);
				c_Desktop->WaitMove(false);
				break;
		}
	}
		
	
}

void LandBattlePanel::gameTrace( const GeneralGameTrace2Head *gameTrace )
{
	unsigned char chBuf[300];
	GeneralGameTrace2Head *ptrace;
	PJunqiTraceInitChip		psetchips;
	memcpy(chBuf,(char *)gameTrace,sizeof(GeneralGameTrace2Head)+gameTrace->chBufLen);
	ptrace = (GeneralGameTrace2Head*)chBuf;
	switch(gameTrace->chType)
	{
		case JUNQI_GAMETRACE_INITCHIP :
		{
			DEBUG_OUTPUT(("JUNQI_GAMETRACE_INITCHIP\n"));
			JUNQI_DEBUG_OUTPUT_ARRANGE((ptrace));
			c_Desktop->Initchip((PJunqiTraceInitChip)(ptrace->chBuf));
			break;
		}
		case JUNQI_GAMETRACE_UNION :
		{
			if(gameTrace->chBuf[0] == 0)
				return;
			AppendData2SaveFile(c_Desktop->c_strSaveFile,(char *)gameTrace,sizeof(GeneralGameTrace2Head)+gameTrace->chBufLen);
			if(c_chUnions>0)
			{
				int i;
				for(i=0;i<c_chUnions;i++)
				{
					if(c_chUnion[i] == gameTrace->chBuf[0])
						return;
				}
			}
			c_chUnion[c_chUnions] = gameTrace->chBuf[0];
			c_chUnions++;
			break;
		}
		case JUNQI_GAMETRACE_UNIONOVER :
			AppendData2SaveFile(c_Desktop->c_strSaveFile,(char *)gameTrace,sizeof(GeneralGameTrace2Head)+gameTrace->chBufLen);
			if(c_chUnions>0)
			{
				int i;
				for(i=0;i<c_chUnions;i++)
				{
					if(c_chUnion[i] == gameTrace->chBuf[0])
					{
						c_chUnion[i] = c_chUnion[c_chUnions-1];
						c_chUnions --;
						c_chUnion[c_chUnions] = 0;
						break;
					}
				}
			}
			break;
		case JUNQI_GAMETRACE_MOVE :
			AppendData2SaveFile(c_Desktop->c_strSaveFile,(char *)gameTrace,sizeof(GeneralGameTrace2Head)+gameTrace->chBufLen);
			c_Desktop->PlayerMoveChip(gameTrace);
			break;
		case JUNQI_GAMETRACE_SETCHIP :
			AppendData2SaveFile(c_Desktop->c_strSaveFile,(char *)gameTrace,sizeof(GeneralGameTrace2Head)+gameTrace->chBufLen);
			c_Desktop->SetPlayerChip((PJunqiSetChip)gameTrace->chBuf);
			break;
		case JUNQI_GAMETRACE_SHOWARRANGE :
		{
			memcpy(chBuf,gameTrace,sizeof(GeneralGameTrace2Head)+gameTrace->chBufLen);
			ptrace = (GeneralGameTrace2Head *)chBuf;
			ptrace->chType = JUNQI_GAMETRACE_INITCHIP;
			AppendData2SaveFile(c_Desktop->c_strSaveLayoutFile,(char *)chBuf,sizeof(GeneralGameTrace2Head)+gameTrace->chBufLen);
			if(c_LastTraceType != JUNQI_GAMETRACE_SHOWARRANGE)
			{
				ClearChessmap(c_Chessmap);
			}
			c_Desktop->Initchip((PJunqiTraceInitChip)(ptrace->chBuf));
			break;
		}
		case JUNQI_GAMETRACE_OVER :
		{
			quint32 uid;
			DJGameUser *puser;
			uid = userIdOfSeat(gameTrace->chSite);
			if(uid != 0)
			{
				puser = gameUser(uid,false);
				if(puser != NULL)
				{
					QString res = puser->userName();
					res += tr(" lost");
					QMessageBox::information(this,tr("game over"),res,QMessageBox::Ok);
				}
			}
			AppendData2SaveFile(c_Desktop->c_strSaveFile,(char *)gameTrace,sizeof(GeneralGameTrace2Head)+gameTrace->chBufLen);
			PMapNode pnodes[30];
			unsigned char chChips = 0;
			int i;
			LandBattleImageItem *pchip;
			chChips = SearchOwnerNodes(c_Chessmap,gameTrace->chBuf[0],pnodes,28,-1);
			if(chChips > 0)
			{
				for(i=0;i<chChips;i++)
				{
					memset(&(pnodes[i]->chip),0,sizeof(CHIP));
					c_Desktop->ClearNodeChip(pnodes[i]);
				}
			}
			break;
		}
	}
	c_LastTraceType = gameTrace->chType;
}

void LandBattlePanel::magicResult( const MagicResult* magicResult )
{
}

void LandBattlePanel::gameOver( const DJGameOver* gameOver )
{
	QString res;
	int i,score;
	quint32 uid;
	DJGameUser *puser;
	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_JUNQI,JUNQI_GAMETRACE_MOVE);
		unsigned int iLen = 0;
		char *p = GetSaveData(c_Desktop->c_strSaveLayoutFile,DJGAME_JUNQI,JUNQI_GAMETRACE_SHOWARRANGE,&iLen);
		if(p == NULL || iLen == 0)
		{
			DEBUG_OUTPUT(("Cant save the layout\n"));
			return;
		}
		AppendData2SaveFile(filename,p,iLen);
		iLen = 0;
		p = GetSaveData(c_Desktop->c_strSaveFile,DJGAME_JUNQI,JUNQI_GAMETRACE_MOVE,&iLen);
		if(p == NULL || iLen == 0)
		{
			DEBUG_OUTPUT(("Cant save the movies\n"));
			return;
		}
		AppendData2SaveFile(filename,p,iLen);
	}
}

void LandBattlePanel::closeEvent( QCloseEvent *e)
{
	if ( isLookingOn() ) {
		//look on
		QByteArray data;
		data.append( c_Table );
		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_Desktop->hasStarted() )
    {
    	QByteArray buf	= makeGameData( DJGAME_PROTOCOL_SUBTYPE_QUIT, QByteArray() );
		DJClientRequest request( buf );
		sendRequest( request, false );
		e->accept();
    }else {
    	e->ignore();
    }
}
/*
void LandBattlePanel::resizeEvent( QResizeEvent * )
{
	s1->setGeometry(0,0,width(),height());
}
*/
