//****************************************************************************
//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 "DJTextBrowser.h"
#include "DJAnimatedImage.h"
#include "DJHttpAnimatedImage.h"
#include "LaunchUrl.h"
#include "DJSchemeEvent.h"

static const int REFRESH_PERIOD			= 100;// 0.1 second
static const int UPDATE_POSITION_PERIOD	= 1000;// 1 second
static const int STAY_DEEP_SECONDS		= 60;//60 second
static const int MAX_ANIMATED_IMAGE		= 10;

DJTextBrowser::DJTextBrowser( QWidget * parent )
	: QTextBrowser( parent )
{
	djDebug() << "DJTextBrowser constructor";
	
	m_posForInsert	= 0;
	m_posForAppend	= 0;
	
	m_timer	= new QTimer(this);
	connect(m_timer,SIGNAL(timeout()),SLOT(updatePosForInsert()));
	m_timer->start(UPDATE_POSITION_PERIOD);
	
	setRefreshEnabled( true );
	startTimer( REFRESH_PERIOD );
	
	connect(this, SIGNAL(textChanged()), SLOT(calculateLength()));
}
DJTextBrowser::~DJTextBrowser()
{
	djDebug() << "DJTextBrowser destructor";
}
void DJTextBrowser::calculateLength()
{
	m_posForAppend	= toPlainText().length();
}
QVariant DJTextBrowser::loadResource ( int type, const QUrl & url )
{
	QString host	= url.host();
	QString path	= url.path();
	djDebug() << "DJTextBrowser loadResource" << type << url.toString() << host << path;
	if ( type != QTextDocument::ImageResource ) {
		return QTextBrowser::loadResource( type, url );
	}
	
	DJAnimatedImage* animatedImage;
	animatedImage	= imageAtUrl(url);
	if ( 0 == animatedImage ) {
		if ( host.isEmpty() ) {
    		QString	imagePath	= QString("images/") + url.toString();
    		animatedImage	= new DJAnimatedImage( imagePath );
    		animatedImage->setName( url );
        	addAnimatedImage( animatedImage );
        	
    	}else {
    		QString localFilePath;
    		if ( host == QUrl(HTTP_WWW_HOST).host() ) {
    			if ( path.startsWith('/') ) {
    				path.remove(0,1);
    			}
    			localFilePath	= path;
    		}
    		animatedImage	 = new DJHttpAnimatedImage( url, localFilePath, this );
    		animatedImage->setName( url );
    		addAnimatedImage( animatedImage );
    		if ( !localFilePath.isEmpty() ) {
    			connect( animatedImage, SIGNAL(httpImageDone()), this, SIGNAL(memberImageDone()) );
    		}
    	}
	}

	return animatedImage->currentImage();
}

void DJTextBrowser::refresh()
{	
	document()->markContentsDirty( 0, m_posForAppend );
}

void DJTextBrowser::setSource ( const QUrl & url )
{
	djDebug() << "DJTextBrowser::setSource" << url;
	QString scheme	= url.scheme();
	if ( scheme.isEmpty() )
		QTextBrowser::setSource(url);
	else if ( scheme == "http" )
		LaunchURL( url );
	else if ( scheme == DJSCHEME ) {
		djDebug() << "DJScheme";
		djDebug()<<"name="<<url.userName()<<"password="<<url.password()
				<<"host="<<url.host()<<"port="<<url.port();
		uint	eventId	= ExtractDJShemeEventID(url);
		switch( eventId ) {
		case DJSCHEME_EVENT_ACCEPT_PRIVATE_VIEW: {
			quint32 userId	= ExtractDJShemeParameter(url).toUInt();
			emit acceptPrivateView( userId );
			break;
		}
		case DJSCHEME_EVENT_ACCEPT_INVITATION: {
			quint8 tableId	= ExtractDJShemeParameter(url).toUInt();
			emit acceptInvitation( tableId, 0 );
			break;
		}
		case DJSCHEME_EVENT_CHECK_INVITATION: {
			quint8 tableId	= ExtractDJShemeParameter(url).toUInt();
			emit checkInvitation( tableId );
			break;
		}
		case DJSCHEME_EVENT_ACCEPT_DRAW_CHESS: {
			emit acceptDrawChess();
			break;
		}
		default:
			break;
		}
	}	
}
void DJTextBrowser::setRefreshEnabled( bool flag )
{
	m_refresh	= flag;
}
void DJTextBrowser::timerEvent ( QTimerEvent * event )
{
	if ( m_refresh ) {
    	foreach(DJAnimatedImage* animatedImage, m_animatedImages) {
    		QUrl	name	= animatedImage->name();
    		document()->addResource(QTextDocument::ImageResource, name, animatedImage->nextImage() );
    	}
        refresh();
	}
}
void DJTextBrowser::addAnimatedImage( DJAnimatedImage* image )
{
	if ( m_animatedImages.size() >= MAX_ANIMATED_IMAGE ) {
		DJAnimatedImage* firstImage	= m_animatedImages.takeFirst();
		delete firstImage;
	}
	m_animatedImages.append( image );
}
DJAnimatedImage* DJTextBrowser::imageAtUrl( const QUrl name )
{
	foreach(DJAnimatedImage* animatedImage, m_animatedImages) {
		if ( name == animatedImage->name() ) {
			return animatedImage;
		}
	}
	return 0;
}
void DJTextBrowser::insertText( const QString & text )
{
	QTextCursor	cursor	= textCursor();
	cursor.setPosition( m_posForInsert );
	setTextCursor( cursor );
	
	QTextBrowser::insertHtml( text );
	QTextBrowser::insertPlainText("\n");
		
	int newPosForInsert	= textCursor().position();
	int delta	= newPosForInsert - m_posForInsert;
	revisePosForRestore( delta );
	
	m_posForInsert	= newPosForInsert;
	
	moveCursorToEnd();
}
void DJTextBrowser::appendText( const QString & text )
{	
	QTextCursor	cursor	= textCursor();
	cursor.setPosition( m_posForAppend );
	setTextCursor( cursor );
	
	QTextBrowser::insertHtml( text );
	QTextBrowser::insertPlainText("\n");
		
	//QTextBrowser::append( text );
		
	QDateTime	triggerTime	= QDateTime::currentDateTime().addSecs( STAY_DEEP_SECONDS );
	InfoForRestore	info;
	info.pos	= m_posForAppend;
	info.time	= triggerTime.toTime_t();
	
	m_infoForRestore << info ;
	
	moveCursorToEnd();
}
void DJTextBrowser::moveCursorToEnd()
{
	QTextCursor	cursor	= textCursor();
	cursor.movePosition( QTextCursor::End );
	setTextCursor( cursor );
}
void DJTextBrowser::revisePosForRestore( int delta )
{
	for ( int i = 0; i < m_infoForRestore.size(); ++i ) {
		m_infoForRestore[i].pos	+= delta;
	}
}
void DJTextBrowser::updatePosForInsert()
{	
	if ( !m_infoForRestore.isEmpty() ) {
		uint	currentTime	= QDateTime::currentDateTime().toTime_t();
		uint	triggerTime	= m_infoForRestore.first().time;
		if ( currentTime >= triggerTime ) {
			InfoForRestore	info	= m_infoForRestore.takeFirst();
			m_posForInsert	= info.pos;
		}
	}
}
/*
void DJTextBrowser::description()
{
	djDebug()<<"DJTextBrowser::description";
	djDebug()<<"m_posForAppend"<<m_posForAppend<<"m_posForInsert"<<m_posForInsert;
	foreach(InfoForRestore info, m_infoForRestore) {
		djDebug()<<"pos"<<info.pos<<"time"<<info.time;
	}
}
*/

