/***************************************************************************
 *   Copyright (C) 2005 by SUZUKI Tasuku                                   *
 *   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 "kkdaddressee.h"
#include "../kkaddressbook/kkacontactdata.h"
#include "../kkaddressbook/kkahomeaddress.h"
#include "../kkaddressbook/kkaofficeaddress.h"

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

#define CORPORATION_SIZE_DECREASE 6
#define SECTION_SIZE_DECREASE 9
#define POST_SIZE_DECREASE 6

using namespace KKDesigner;

KKDAddressee::KKDAddressee( const QPoint& l
						  , const QSize& s
						  , const QFont& f
						  , const QColor& c
						  , Orientation o
						  , QObject* parent
						  )
	: KKDTextBase( l, s, f, c, o, parent )
{
}

KKDAddressee::KKDAddressee( QDomElement e, QObject* parent )
	: KKDTextBase( e, parent )
{
}

KKDAddressee::KKDAddressee( const KKDAddressee* item, QObject* parent )
	: KKDTextBase( (KKDTextBase*)item, parent )
{
}

KKDAddressee::~KKDAddressee()
{
}

QDomElement KKDAddressee::toElement( QDomDocument& doc, const QString& t )
{
	QString tag( t == QString::null ? tagName() : t );
	return KKDTextBase::toElement( doc, tag );
}

void KKDAddressee::drawItemBefore( QRect& r, QPainter& p, DrawMode m, const KKAddressBook::KKAContactData* d )
{
	KKDTextBase::drawItemBefore( r, p, m, d );
	switch( m )
	{
		case AddressMode:
		case PrintMode:
			if( d != NULL )
			{
				switch( d->const_current()->locationType() )
				{
					case KKAddressBook::KKAAddressData::Home:
						drawTextHome( r, p, d );
						break;
					case KKAddressBook::KKAAddressData::Office:
						drawTextOffice( r, p, d );
						break;
					default:
						break;
				}
			}
			break;
		default:
			drawText( r, p, AlignCenter, i18n( "@Addressee" ) );
			break;
	}
}

void KKDAddressee::drawItemAfter( QRect& r, QPainter& p, DrawMode m, const KKAddressBook::KKAContactData* d )
{
	KKDTextBase::drawItemAfter( r, p, m, d );
	switch( m )
	{
		case DesignMode:
		{
			QPixmap pxm = SmallIcon( "kk_addressee" );
			p.drawPixmap( QRect( rect().topLeft(), pxm.size() ), pxm );
			break;
		}
		default:
			break;
	}
}

void KKDAddressee::drawTextHome( QRect& r, QPainter& p, const KKAddressBook::KKAContactData* d )
{
	QPtrList<KKAddressBook::KKAPersonalData> persons( *d->const_home() );
	persons.prepend( d );

	for( int i = persons.count(); i >= 0; i-- )
	{
		if( !persons.at( i ) || !persons.at( i )->isValid() ) persons.remove( i );
	}

	if( persons.count() == 0 ) return;

	switch( orientation() )
	{
		case Horizontal:
		{
			int height = 0;
			int width[4] = { 0, 0, 0, 0 };
			int sep_width = calcSize( " " ).width() / 2;
			QSize layout[persons.count()][4];
			QRect rct( rect() );
			int size_decrease = 0;
			while( 1 )
			{
				sep_width = calcSize( " ", size_decrease ).width() / 2;
				height = 0;
				for( int i = 0; i != 4; i++ )
				{
					width[i] = 0;
				}
				QSize totalSize;
				for( uint i = 0; i != persons.count(); i++ )
				{
					QSize s = calcSize( persons.at( i )->prefix(), size_decrease );
					if( width[0] < s.width() ) width[0] = s.width();
					layout[i][0] = s;

					s = calcSize( persons.at( i )->familyName(), size_decrease );
					if( width[1] < s.width() ) width[1] = s.width();
					layout[i][1] = s;

					s = calcSize( persons.at( i )->givenName(), size_decrease );
					if( width[2] < s.width() ) width[2] = s.width();
					layout[i][2] = s;

					s = calcSize( persons.at( i )->suffix(), size_decrease );
					if( width[3] < s.width() ) width[3] = s.width();
					layout[i][3] = s;

					height += layout[i][2].height();
					totalSize.setHeight( totalSize.height() + layout[i][2].height() );
				}
				totalSize.setWidth( width[0] + width[1] + width[2] + width[3]
								 	 + ( width[0] == 0 ? 0 : sep_width )
								 	 + ( width[1] == 0 ? 0 : sep_width * 2 )
								 	 + ( width[3] == 0 ? 0 : sep_width )
									);
				if( rct.width() < totalSize.width() || rct.height() < totalSize.height() )
				{
					size_decrease++;
				}
				else
				{
					break;
				}
			}
/*			if( rct.height() > height )
			{
				rct.moveTop( rect().top() + ( rect().height() - height ) / 2 );
			}*/
			rct.setHeight( height / persons.count() );
			for( uint i = 0; i != persons.count(); i++ )
			{
				int max_width = width[1] + width[2] + sep_width * 2;
				if( width[0] > 0 ) max_width += width[0] + sep_width;
				if( width[3] > 0 ) max_width += width[3] + sep_width;
				if( rect().width() > max_width )
				{
					rct.moveLeft( rect().left() + ( rect().width() - max_width ) / 2 );
				}
				if( width[0] > 0 )
				{
					rct.setWidth( width[0] );
					drawText( rct, p, AlignRight, persons.at( i )->prefix(), size_decrease );
					rct.moveLeft( rct.left() + width[0] + sep_width );
				}
				if( width[1] > 0 )
				{
					rct.setWidth( width[1] );
					drawText( rct, p, AlignCenter, persons.at( i )->familyName(), size_decrease );
					rct.moveLeft( rct.left() + width[1] );
				}
				if( width[2] > 0 )
				{
					if( width[1] > 0 )
					{
						rct.moveLeft( rct.left() + sep_width * 2 );
					}
					rct.setWidth( width[2] );
					drawText( rct, p, AlignCenter, persons.at( i )->givenName(), size_decrease );
					rct.moveLeft( rct.left() + width[2] );
				}
				if( width[3] > 0 )
				{
					if( width[1] > 0 )
					{
						rct.moveLeft( rct.left() + sep_width );
					}
					rct.setWidth( width[3] );
					drawText( rct, p, AlignLeft, persons.at( i )->suffix(), size_decrease );
					rct.moveLeft( rct.left() + width[3] );
				}
				rct.moveTop( rct.top() + height / persons.count() );
			}

			break;
		}
		case Vertical:
		{
			int width = 0;
			int height[4] = { 0, 0, 0, 0 };
			QSize layout[persons.count()][4];
			uint max_length[4] = { 0, 0, 0, 0 };
			QRect rct( rect() );
			int size_decrease = 0;
			int sep_height = 0;
			while( 1 )
			{
				sep_height = calcSize( " ", size_decrease ).width() / 2;
				width = 0;
				for( int i = 0; i != 4; i++ )
				{
					height[i] = 0;
					max_length[i] = 0;
				}
				QSize totalSize;
				for( uint i = 0; i != persons.count(); i++ )
				{
					QSize s = calcSize( persons.at( i )->prefix(), size_decrease );
					if( height[0] < s.height() ) height[0] = s.height();
					if( max_length[0] < persons.at( i )->prefix().length() ) max_length[0] = persons.at( i )->prefix().length();
					layout[i][0] = s;

					s = calcSize( persons.at( i )->familyName(), size_decrease );
					if( height[1] < s.height() ) height[1] = s.height();
					if( max_length[1] < persons.at( i )->familyName().length() ) max_length[1] = persons.at( i )->familyName().length();
					layout[i][1] = s;

					s = calcSize( persons.at( i )->givenName(), size_decrease );
					if( height[2] < s.height() ) height[2] = s.height();
					if( max_length[2] < persons.at( i )->givenName().length() ) max_length[2] = persons.at( i )->givenName().length();
					layout[i][2] = s;

					s = calcSize( persons.at( i )->suffix(), size_decrease );
					if( height[3] < s.height() ) height[3] = s.height();
					if( max_length[3] < persons.at( i )->suffix().length() ) max_length[3] = persons.at( i )->suffix().length();
					layout[i][3] = s;

					width += layout[i][2].width();
					totalSize.setWidth( layout[i][2].width() );
				}
				totalSize.setHeight( height[0] + height[1] + height[2] + height[3]
								 	 + ( height[0] == 0 ? 0 : sep_height )
								 	 + ( height[1] == 0 ? 0 : sep_height * 2 )
								 	 + ( height[3] == 0 ? 0 : sep_height )
									);
				if( rct.width() < totalSize.width() || rct.height() < totalSize.height() )
				{
					size_decrease++;
				}
				else
				{
					break;
				}
			}

			rct.setWidth( width / persons.count() );
			if( rect().width() > width )
			{
				rct.moveRight( rect().right() - ( rect().width() - width ) / 2 );
			}
			else
			{
				rct.moveRight( rect().right() );
			}

			for( uint i = 0; i != persons.count(); i++ )
			{
				int name_height = rect().height() - sep_height * 2;
				if( height[0] > 0 ) name_height -= height[0] + sep_height;
				if( height[3] > 0 ) name_height -= height[3] + sep_height;
				name_height /= ( max_length[1] + max_length[2] );
				rct.moveTop( rect().top() );

				if( height[0] > 0 )
				{
					rct.setHeight( height[0] );
					drawText( rct, p, AlignBottom, persons.at( i )->prefix(), size_decrease );
					rct.moveTop( rct.top() + height[0] + sep_height );
				}
				if( height[1] > 0 )
				{
					rct.setHeight( name_height );
					rct.moveTop( rct.top() + ( max_length[1] - persons.at( i )->familyName().length() ) * name_height / 2 );
					for( uint j = 0; j != persons.at( i )->familyName().length(); j++ )
					{
						drawText( rct, p, AlignCenter, persons.at( i )->familyName().mid( j, 1 ), size_decrease );
						rct.moveTop( rct.top() + name_height );
					}
					rct.moveTop( rct.top() + ( max_length[1] - persons.at( i )->familyName().length() ) * name_height / 2 );
				}
				if( height[2] > 0 )
				{
					if( height[1] > 0 )
					{
						rct.moveTop( rct.top() + sep_height * 2 );
					}
					rct.setHeight( name_height );
					rct.moveTop( rct.top() + ( max_length[2] - persons.at( i )->givenName().length() ) * name_height / 2 );
					for( uint j = 0; j != persons.at( i )->givenName().length(); j++ )
					{
						drawText( rct, p, AlignCenter, persons.at( i )->givenName().mid( j, 1 ), size_decrease );
						rct.moveTop( rct.top() + name_height );
					}
					rct.moveTop( rct.top() + ( max_length[2] - persons.at( i )->givenName().length() ) * name_height / 2 );
				}
				if( height[3] > 0 )
				{
					if( height[1] > 0 )
					{
						rct.moveTop( rct.top() + sep_height );
					}
					rct.setHeight( height[3] );
					drawText( rct, p, AlignTop, persons.at( i )->suffix(), size_decrease );
					rct.moveTop( rct.top() + height[3] );
				}
				rct.moveRight( rct.right() - width / persons.count() );
			}

			break;
		}
	}
}

void KKDAddressee::drawTextOffice( QRect& r, QPainter& p, const KKAddressBook::KKAContactData* d )
{
	QString prefix = d->prefix();
	QString familyName = d->familyName();
	QString givenName = d->givenName();
	QString suffix = d->suffix();

	QString corporation = d->const_office()->corporation();
	QString section = d->const_office()->section();
	QString post = d->const_office()->post();

	QRect rct( rect() );
	int right = rct.right();
	int main_width = 0;
	int sub_width = 0;

	switch( orientation() )
	{
		case Horizontal:
		{
			int height = 0;
			int sep_width = 0;
			int size_decrease = 0;
			while( 1 )
			{
				QSize totalSize;
				sep_width = calcSize( " ", size_decrease ).width();
				if( !corporation.isEmpty() )
				{
					QSize s = calcSize( corporation, size_decrease + CORPORATION_SIZE_DECREASE );
					if( totalSize.width() < s.width() ) totalSize.setWidth( s.width() );
					totalSize.setHeight( totalSize.height() + s.height() );
				}
				if( !section.isEmpty() )
				{
					QSize s = calcSize( section, size_decrease + SECTION_SIZE_DECREASE );
					if( totalSize.width() < s.width() ) totalSize.setWidth( s.width() );
					totalSize.setHeight( totalSize.height() + s.height() );
				}
				if( d->isValid() )
				{
					QSize sz;
					if( !post.isEmpty() )
					{
						QSize s = calcSize( post, size_decrease + POST_SIZE_DECREASE );
						if( sz.height() < s.height() ) sz.setHeight( s.height() );
						sz.setWidth( sz.width() + s.width() + sep_width );
					}
					if( !prefix.isEmpty() )
					{
						QSize s = calcSize( prefix, size_decrease );
						if( sz.height() < s.height() ) sz.setHeight( s.height() );
						sz.setWidth( sz.width() + s.width() + sep_width );
					}
					if( !familyName.isEmpty() )
					{
						QSize s = calcSize( familyName, size_decrease );
						if( sz.height() < s.height() ) sz.setHeight( s.height() );
						sz.setWidth( sz.width() + s.width() + sep_width * 2 );
					}
					if( !givenName.isEmpty() )
					{
						QSize s = calcSize( givenName, size_decrease );
						if( sz.height() < s.height() ) sz.setHeight( s.height() );
						sz.setWidth( sz.width() + s.width() );
					}
					if( !suffix.isEmpty() )
					{
						QSize s = calcSize( suffix, size_decrease );
						if( sz.height() < s.height() ) sz.setHeight( s.height() );
						sz.setWidth( sz.width() + s.width() + sep_width );
					}
					if( totalSize.width() < sz.width() ) totalSize.setWidth( sz.width() );
					totalSize.setHeight( totalSize.height() + sz.height() );
					height = sz.height();
				}
				if( rct.width() < totalSize.width() || rct.height() < totalSize.height() )
				{
					size_decrease++;
				}
				else
				{
					break;
				}
			}
			if( !corporation.isEmpty() )
			{
				QSize s = calcSize( corporation, size_decrease + CORPORATION_SIZE_DECREASE );
				rct.setWidth( s.width() );
				rct.setHeight( s.height() );
				drawText( rct, p, AlignLeft, corporation, size_decrease + CORPORATION_SIZE_DECREASE );
				rct.moveTop( rct.top() + rct.height() );
			}
			if( !section.isEmpty() )
			{
				QSize s = calcSize( section, size_decrease + SECTION_SIZE_DECREASE );
				rct.setWidth( s.width() );
				rct.setHeight( s.height() );
				rct.moveLeft( rct.left() + sep_width );
				drawText( rct, p, AlignLeft, section, size_decrease + SECTION_SIZE_DECREASE );
				rct.moveLeft( rct.left() - sep_width );
				rct.moveTop( rct.top() + rct.height() );
			}
			if( d->isValid() )
			{
				int left = 0;
				int width = rect().width();
				rct.setHeight( height );
				if( !post.isEmpty() )
				{
					QSize s = calcSize( post, size_decrease + POST_SIZE_DECREASE );
					rct.setWidth( s.width() );
// 					p.drawRect( rct );
					drawText( rct, p, AlignLeft, post, size_decrease + POST_SIZE_DECREASE );
					rct.moveLeft( rct.left() + s.width() + sep_width );
					width -= s.width() + sep_width;
				}
				if( !prefix.isEmpty() )
				{
					QSize s = calcSize( prefix, size_decrease );
					rct.setWidth( s.width() );
					drawText( rct, p, AlignRight, prefix, size_decrease );
					rct.moveLeft( rct.left() + s.width() + sep_width );
					width -= s.width() + sep_width;
				}
				left = rct.left();
				if( !suffix.isEmpty() )
				{
					QSize s = calcSize( suffix, size_decrease );
					rct.setWidth( s.width() );
					rct.moveLeft( rect().right() - s.width() );
					drawText( rct, p, AlignLeft, suffix, size_decrease );
					width -= s.width() + sep_width;
				}
				int char_width = familyName.isEmpty() ? width / givenName.length() : ( width - sep_width * 2 ) / ( familyName.length() + givenName.length() );
				rct.moveLeft( left );
				rct.setWidth( char_width );
				if( !familyName.isEmpty() )
				{
					for( uint i = 0; i != familyName.length(); i++ )
					{
						drawText( rct, p, AlignHCenter, familyName.mid( i, 1 ), size_decrease );
						rct.moveLeft( rct.left() + char_width );
					}
					rct.moveLeft( rct.left() + sep_width * 2 );
				}
				for( uint i = 0; i != givenName.length(); i++ )
				{
					drawText( rct, p, AlignHCenter, givenName.mid( i, 1 ), size_decrease );
					rct.moveLeft( rct.left() + char_width );
				}
			}
			break;
		}
		case Vertical:
		{
			int sep_height = 0;
			int size_decrease = 0;
			while( 1 )
			{
				main_width = 0;
				sub_width = 0;
				QSize totalSize;
				sep_height = calcSize( " ", size_decrease ).height() / 2;
				if( !corporation.isEmpty() )
				{
					QSize s = calcSize( corporation, size_decrease + CORPORATION_SIZE_DECREASE );
					if( totalSize.height() < s.height() ) totalSize.setHeight( s.height() );
					totalSize.setWidth( totalSize.width() + s.width() );
					sub_width += s.width();
				}
				if( !section.isEmpty() )
				{
					QSize s = calcSize( section, size_decrease + SECTION_SIZE_DECREASE );
					if( totalSize.height() < s.height() ) totalSize.setHeight( s.height() );
					totalSize.setWidth( totalSize.width() + s.width() );
					sub_width += s.width();
				}
				if( d->isValid() )
				{
					QSize sz;
					if( !post.isEmpty() )
					{
						QSize s = calcSize( post, size_decrease + POST_SIZE_DECREASE );
						if( sz.width() < s.width() ) sz.setWidth( s.width() );
						sz.setHeight( sz.height() + s.height() + sep_height );
					}
					if( !prefix.isEmpty() )
					{
						QSize s = calcSize( prefix, size_decrease );
						if( sz.width() < s.width() ) sz.setWidth( s.width() );
						sz.setHeight( sz.height() + s.height() + sep_height );
					}
					if( !familyName.isEmpty() )
					{
						QSize s = calcSize( familyName, size_decrease );
						if( sz.width() < s.width() ) sz.setWidth( s.width() );
						sz.setHeight( sz.height() + s.height() );
					}
					if( !givenName.isEmpty() )
					{
						if( !familyName.isEmpty() )
						{
							sz.setHeight( sz.height() + sep_height * 2 );
						}
						QSize s = calcSize( givenName, size_decrease );
						if( sz.width() < s.width() ) sz.setWidth( s.width() );
						sz.setHeight( sz.height() + s.height() );
					}
					if( !suffix.isEmpty() )
					{
						QSize s = calcSize( suffix, size_decrease );
						if( sz.width() < s.width() ) sz.setWidth( s.width() );
						sz.setHeight( sz.height() + s.height() + sep_height );
					}
					main_width = sz.width();
					if( totalSize.height() < sz.height() ) totalSize.setHeight( sz.height() );
					totalSize.setWidth( totalSize.width() + sz.width() );
				}
				if( rct.width() < totalSize.width() || rct.height() < totalSize.height() )
				{
					size_decrease++;
				}
				else if( ( rct.width() - main_width ) / 2 < sub_width )
				{
					size_decrease++;
				}
				else
				{
					right = rct.right() - ( rct.width() - main_width ) / 2 + sub_width;
					break;
				}
			}

			int top = rct.top();
			if( !corporation.isEmpty() )
			{
				QSize s = calcSize( corporation, size_decrease + CORPORATION_SIZE_DECREASE );
				rct.setWidth( s.width() );
				rct.moveRight( right );
				drawText( rct, p, AlignTop, corporation, size_decrease + CORPORATION_SIZE_DECREASE );
				right -= s.width();
			}
			if( !section.isEmpty() )
			{
				QSize s = calcSize( section, size_decrease + SECTION_SIZE_DECREASE );
				rct.setWidth( s.width() );
				rct.moveRight( right );
				rct.moveTop( rct.top() + sep_height );
				rct.setHeight( rct.height() - sep_height );
				drawText( rct, p, AlignTop, section, size_decrease + SECTION_SIZE_DECREASE );
				rct.moveTop( rct.top() - sep_height );
				rct.setHeight( rct.height() + sep_height );
				right -= s.width();
			}
			if( d->isValid() )
			{
				int height = rect().height();
				rct.setWidth( calcSize( givenName ).width() );
				rct.moveRight( right );

				if( !post.isEmpty() )
				{
					QSize s = calcSize( post, size_decrease + POST_SIZE_DECREASE );
					rct.setHeight( s.height() + sep_height );
					drawText( rct, p, AlignTop, post, size_decrease + POST_SIZE_DECREASE );
					top += s.height() + sep_height;
					height -= s.height() + sep_height;
				}
				if( !prefix.isEmpty() )
				{
					QSize s = calcSize( prefix, size_decrease );
					rct.setHeight( s.height() );
					rct.moveTop( top );
					drawText( rct, p, AlignTop, prefix, size_decrease );
					top += s.height() + sep_height;
					height -= s.height() + sep_height;
				}
				if( !suffix.isEmpty() )
				{
					QSize s = calcSize( suffix, size_decrease );
					rct.setHeight( s.height() );
					rct.moveBottom( rect().bottom() );
					drawText( rct, p, AlignTop, suffix, size_decrease );
					height -= s.height() + sep_height;
				}
				int char_height = familyName.isEmpty() ? height / givenName.length() : ( height - sep_height * 2 ) / ( familyName.length() + givenName.length() );
				rct.moveTop( top );
				rct.setHeight( char_height );
				if( !familyName.isEmpty() )
				{
					for( uint i = 0; i != familyName.length(); i++ )
					{
						drawText( rct, p, AlignCenter, familyName.mid( i, 1 ), size_decrease );
						rct.moveTop( rct.top() + char_height );
					}
					rct.moveTop( rct.top() + sep_height * 2 );
				}
				for( uint i = 0; i != givenName.length(); i++ )
				{
					drawText( rct, p, AlignCenter, givenName.mid( i, 1 ), size_decrease );
					rct.moveTop( rct.top() + char_height );
				}
			}
			break;
		}
	}
}
