/***************************************************************************
 *   Copyright (C) 2004 by Tasuku Suzuki                                   *
 *   tasuku@linux-life.net                                                 *
 *                                                                         *
 *   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; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include <qregexp.h>
#include <qimage.h>
#include <qpixmap.h>
#include <qdatastream.h>

#include <kiconloader.h>
#include <kmdcodec.h>
#include <klocale.h>
#include <kdebug.h>

#include "kkitem.h"
#include "kkaddressbook/kkcontactdata.h"

KKItem::KKItem( QListViewItem* parent, KKItem* item )
	: QObject( (QWidget*)0 ), KListViewItem( parent )
{
	m_locked = false;
	setPixmap( 0, SmallIcon("frame_edit") );
	setName( item->name() );
	setLocation( item->location() );
	setSize( item->size() );
	setText( item->text() );
	setTextAlign( item->textAlign() );
	setTextOrientation( item->textOrientation() );
	setTextColor( item->textColor() );
	setTextFont( item->textFont() );
	if( !item->image().isNull() )
	{
		setImage( item->image() );
		m_resizedimagecache = item->image();
	}
	setImagePrint( item->imagePrint() );
	setLocked( item->locked() );
	m_isBase = false;
	m_datafield = 0;
}

KKItem::KKItem( QListViewItem* parent, const char* name )
	: QObject( (QWidget*)0, name ), KListViewItem( parent )
{
	setPixmap( 0, SmallIcon("frame_edit") );
	setText( 0, i18n( "Item" ) );
	m_text = "";
	m_textAlign = AlignCenter;
	m_textOrientation = Horizontal;
	m_textColor = black;
	m_textFont = listView()->font();
	m_imagePrint = true;
	m_isBase = false;
	m_datafield = 0;
	m_locked = false;
}

KKItem::KKItem( QDomElement doc, KListViewItem* parent, const char* name )
	: QObject( (QWidget*)0, name ), KListViewItem( parent )
{
	setPixmap( 0, SmallIcon("frame_edit") );
	m_isBase = false;
	parse( doc );
}

KKItem::KKItem( QDomElement doc, KListView* parent, const char* name )
	: QObject( (QWidget*)0, name ), KListViewItem( parent )
{
	setPixmap( 0, SmallIcon("filenew") );
	m_isBase = true;
	parse( doc );
}

void KKItem::parse( QDomElement& e )
{
	m_selected = false;

	setText( 0, e.attribute( "name" ) );
	m_location.setX( e.hasAttribute( "x" ) ? e.attribute( "x" ).toInt() : 0 );
	m_location.setY( e.hasAttribute( "y" ) ? e.attribute( "y" ).toInt() : 0 );

	m_size.setWidth( e.hasAttribute( "width" ) ? e.attribute( "width" ).toInt() : 10 );
	m_size.setHeight( e.hasAttribute( "height" ) ? e.attribute( "height" ).toInt() : 10 );

	m_text = e.hasAttribute( "text" ) ? e.attribute( "text" ) : "";
	m_textOrientation = e.hasAttribute( "textorientation" ) ? ((Orientation)e.attribute( "textorientation" ).toInt()) : Horizontal;
	m_textAlign = e.hasAttribute( "textalign" ) ? e.attribute( "textalign" ).toInt() : AlignCenter;
	m_textColor = e.hasAttribute( "textcolor" ) ? QColor( e.attribute( "textcolor" ) ) : black;
	if( e.hasAttribute( "textfont" ) && !e.attribute( "textfont" ).isEmpty() )
	{
		QFont f;
		if( f.fromString( e.attribute("textfont" ) ) )
		{
			m_textFont = f;
		}
	}
	else
	{
		m_textFont = listView()->font();
	}

	m_datafield = e.hasAttribute( "datafield" ) ? e.attribute( "datafield" ).toInt() : 0;

	if( e.hasAttribute( "image" ) && !e.attribute( "image" ).isEmpty() )
	{
		QByteArray borg, bdec;
		borg = e.attribute( "image" ).utf8();
		KCodecs::base64Decode( borg, bdec );
		QDataStream stream( bdec, IO_ReadOnly );
		QPixmap p;
		stream >> p;
		m_image = p.convertToImage();
	}

	m_imagePrint = e.hasAttribute( "imageprint" );
	m_locked = e.hasAttribute( "locked" );

	listView()->setOpen( this, e.hasAttribute( "selected" ) );
	listView()->setSelected( this, e.hasAttribute( "selected" ) );

	for( QDomNode n = e.lastChild(); !n.isNull(); n = n.previousSibling() )
	{
		switch( n.nodeType() )
		{
			case QDomNode::ElementNode:
				new KKItem( n.toElement(), this );
				break;
			default:
				break;
		}
	}
}

KKItem::~KKItem()
{
}

// BEGIN Properties

// BEGIN Name
void KKItem::setName( const QString &n )
{
	if( locked() ) return;
	if( n == name() ) return;
	setText( 0, n );
	emit nameChanged();
}
// END

// BEGIN Location
void KKItem::setLocation( const QPoint &l )
{
	if( locked() ) return;
	if( l == location() ) return;
	QRect r = rect();
	m_location = l;
	emit repaint( r | rect() );
	emit locationChanged();
}
// END

// BEGIN Size
void KKItem::setSize( const QSize &s )
{
	if( locked() ) return;
	if( s == size() ) return;
	QRect r = rect();
	m_size = s;
	emit repaint( r | rect() );
	emit sizeChanged();
}
// END

// BEGIN Text
void KKItem::setText( const QString &t )
{
	if( locked() ) return;
	if( t == text() ) return;
	m_text = t;
	emit repaint( rect() );
	emit textChanged();
}
// END

// BEGIN TextAlign
void KKItem::setTextAlign( unsigned int a )
{
	if( locked() ) return;
	if( a == textAlign() ) return;
	m_textAlign = a;
	emit repaint( rect() );
	emit textAlignChanged();
}
// END

// BEGIN TextOrientation
void KKItem::setTextOrientation( Orientation o )
{
	if( locked() ) return;
	if( o == textOrientation() ) return;
	m_textOrientation = o;
	emit repaint( rect() );
	emit textOrientationChanged();
}
// END

// BEGIN TextColor
void KKItem::setTextColor( const QColor &c )
{
	if( locked() ) return;
	if( c == textColor() ) return;
	m_textColor = c;
	emit repaint( rect() );
	emit textColorChanged();
}
// END

// BEGIN Font
void KKItem::setTextFont( const QFont &f )
{
	if( locked() ) return;
	if( f == textFont() ) return;
	m_textFont = f;
	emit repaint( rect() );
	emit textFontChanged();
}
// END

// BEGIN DataField
void KKItem::setDataField( int d )
{
	if( locked() ) return;
	if( d == datafield() ) return;
	m_datafield = d;
	emit datafieldChanged();
}

// END DataField

// BEGIN Image
void KKItem::setImage( const QImage &i )
{
	if( locked() ) return;
	if( i == image() ) return;
	m_image = i;
        m_resizedimagecache = m_image;
	emit repaint( rect() );
	emit imageChanged();
}
// END

// BEGIN Orientation
void KKItem::setOrientation( Orientation o )
{
	if( locked() ) return;
	if( o == orientation() ) return;
	QSize s = size();
	switch( o )
	{
		case Horizontal:
			if( s.width() < s.height() )
			{
				m_size = QSize( s.height(), s.width() );
			}
			break;
		case Vertical:
			if( s.width() > s.height() )
			{
				m_size = QSize( s.height(), s.width() );
			}
			break;
	}
	emit repaint( rect() );
	emit orientationChanged();
}
// END

// BEGIN Print
void KKItem::setImagePrint( bool p )
{
	if( locked() ) return;
	m_imagePrint = p;
	emit imagePrintChanged();
}
// END

// BEGIN Locked
void KKItem::setLocked( bool l )
{
	m_locked = l;
	emit repaint( rect() );
	emit lockedChanged();
}
// END

// END   Properties

void KKItem::setSelected( bool b )
{
	KListViewItem::setSelected( b );
	emit selectionChanged( b );
	emit selectionChanged( this, b );
	emit repaint( rect() );
}

void KKItem::drawItem( QPainter& p, double zoom, const KKContactData *data )
{
	p.setPen( gray );
	if( isSelected() )
	{
		p.setPen( locked() ? red : blue );
	}
	QRect r( location()*zoom, size()*zoom );

	if( !data )
	{
		p.drawLine( r.topLeft(), r.topRight() );
		p.drawLine( r.topRight(), r.bottomRight() );
		p.drawLine( r.bottomRight(), r.bottomLeft() );
		p.drawLine( r.bottomLeft(), r.topLeft() );
		r.setRect( r.left() + 1, r.top() + 1, r.width() - 2, r.height() - 2 );
	}
	if( !image().isNull() )
	{
		if( data )
		{
			// when printing
			if( imagePrint() )
			{
				p.drawImage( r, imageResized() );
			}
		}
		else
		{
			// when editing,previewing
			if( QListViewItem::parent() )
			{
				p.drawImage( r, imageResized() );
			}
		}
	}
	if( data && datafield() )
	{
		switch( datafield() )
		{
			case 1:
			case 2:
			case 3:
			case 4:
			case 5:
			case 6:
			case 7:
				if( !data->getZipCode().isEmpty() )
				{
					QString zipCode = data->getZipCode();
					zipCode.remove( '-' );
					drawText( p, r, QString( zipCode[datafield()-1] ) );
				}
				break;
			case 8:	// Direction
				if( !data->getFullname().isEmpty() )
				{
					QString direction = data->getFullname();
					if( !data->getNameSuffix().isEmpty() )
						direction += data->getNameSuffix();
					
					drawText( p, r, direction );
				}
				break;
			case 9:	// Address
				if( !data->getAddress1().isEmpty() )
				{
					drawText( p, r, data->getAddress1() + data->getAddress2() );
				}
				break;
		}
	}
	else if( !text().isEmpty() )
	{
		drawText( p, r, text() );
	}

	if( isSelected() && locked() && !data )
	{
		QPixmap pxmLocked = SmallIcon( "encrypted" );
		QRect rLocked( r.topRight() - QPoint( pxmLocked.width(), 0 ), pxmLocked.size() );
		p.drawPixmap( rLocked, pxmLocked );
	}
}


void KKItem::drawText( QPainter& p, const QRect& r, const QString &text )
{
	p.setPen( textColor() );
	p.setFont( textFont() );
	if( textOrientation() == Horizontal )
	{
		p.drawText( r, textAlign(), text );
		return;
	}
	QStringList org = QStringList::split( "\n", text, true );
	QStringList disp;
	for( QStringList::Iterator it = org.begin(); it != org.end(); ++it )
	{
		QStringList line = QStringList::split( QString(""), *it, true );
		line.pop_front();
		line.pop_back();
		QString tmp = line.join( "\n" );

		QRegExp hyphen( QString::fromUtf8("[-ーｰ－-]") );
		tmp.replace( hyphen, "|" );

		QRegExp rx( "([0-9])\n([0-9])" );
		while( rx.search( tmp ) != -1 )
		{
			tmp.replace( rx, "\\1\\2" );
		}
		disp.append( tmp );
	}

	int* width = new int[disp.count()];
	QFontMetrics met( textFont() );
	for( unsigned int i = 0; i != disp.count(); i++ )
	{
		width[i] = 0;
		QStringList line = QStringList::split( "\n", disp[i], true );
		for( QStringList::Iterator it = line.begin(); it != line.end(); ++it )
		{
			if( width[i] < met.width( *it ) )
			{
				width[i] = met.width( *it );
			}
		}
	}
	int right = r.width();
	for( unsigned int i = 0; i != disp.count(); i++ )
	{
		right -= width[i];
	}
	switch( textAlign() & AlignHorizontal_Mask )
	{
		case AlignLeft:
			right = r.right() - right;
			break;
		case AlignHCenter:
			right = r.right() - right / 2;
			break;
		case AlignRight:
			right = r.right();
			break;
	}
	for( unsigned int i = 0; i != disp.count(); i++ )
	{
		QRect rct( right - width[i], r.top(), width[i], r.height() );
		if( r.contains( rct ) )
		{
			p.drawText( rct, AlignHCenter | ( textAlign() & AlignVertical_Mask ), disp[i] );
		}
		right -= width[i];
	}
	delete[] width;
}

QDomElement KKItem::toElement( QDomDocument& doc )
{
	QDomElement elem = doc.createElement( "item" );
	if( !QListViewItem::parent() )
	{
		KKItem* child = (KKItem*)firstChild();
		while( child )
		{
			elem.appendChild( child->toElement( doc ) );
			child = (KKItem*)child->nextSibling();
		}
		elem.setAttribute( "orientation", orientation() );
	}
	else
	{
		elem.setAttribute( "x", location().x() );
		elem.setAttribute( "y", location().y() );
		elem.setAttribute( "text", text() );
		elem.setAttribute( "textalign", textAlign() );
		elem.setAttribute( "textorientation", textOrientation() );
		elem.setAttribute( "textcolor", textColor().name() );
		elem.setAttribute( "textfont", textFont().toString() );

		elem.setAttribute( "datafield", datafield() );
	}
	elem.setAttribute( "name", text(0) );
	elem.setAttribute( "width", size().width() );
	elem.setAttribute( "height", size().height() );

	if( !image().isNull() )
	{
		QByteArray borg, benc;
		QDataStream stream( borg, IO_WriteOnly );
		QPixmap p;
		p.convertFromImage( m_image );
		stream << p;
		KCodecs::base64Encode( borg, benc );
		elem.setAttribute( "image", benc );
	}
	if( m_imagePrint ) elem.setAttribute( "imageprint", 1 );
	if( m_locked ) elem.setAttribute( "locked", 1 );
	if( isSelected() ) elem.setAttribute( "selected", 1 );
	return elem;
}
