/* This file is part of the KDE project
   Copyright (C) 2004 Lucijan Busch <lucijan@kde.org>
   Copyright (C) 2004-2005 Jaroslaw Staniek <js@iidea.pl>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this program; see the file COPYING.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
*/

#include <tqpainter.h>
#include <tqpixmap.h>
#include <tqcolor.h>
#include <tqapplication.h>
#include <tqpointarray.h>

#include <kdebug.h>

#include <math.h>

#include "kexirelationview.h"
#include "kexirelationviewtable.h"
#include "kexirelationviewconnection.h"
#include <kexidb/tableschema.h>
#include <kexidb/utils.h>
#include <core/kexi.h>

//#include "r1.xpm"
//#include "rn.xpm"

KexiRelationViewConnection::KexiRelationViewConnection(
	KexiRelationViewTableContainer *masterTbl, KexiRelationViewTableContainer *detailsTbl, 
	SourceConnection &c, KexiRelationView *parent)
{
	m_parent = parent;
//	kdDebug() << "KexiRelationViewConnection::KexiRelationViewConnection()" << endl;

	m_masterTable = masterTbl;
	if(!masterTbl || !detailsTbl)
	{
		kdDebug() << "KexiRelationViewConnection::KexiRelationViewConnection(): expect sig11" << endl;
		kdDebug() << "KexiRelationViewConnection::KexiRelationViewConnection()" << masterTbl << endl;
		kdDebug() << "KexiRelationViewConnection::KexiRelationViewConnection()" << detailsTbl << endl;
	}

	m_detailsTable = detailsTbl;
	m_masterField = c.masterField;
	m_detailsField = c.detailsField;

	m_selected = false;
}

KexiRelationViewConnection::~KexiRelationViewConnection()
{
}

void
KexiRelationViewConnection::drawConnection(TQPainter *p)
{
	p->setPen(m_parent->palette().active().foreground());
	int sx = m_masterTable->x() + m_masterTable->width() + m_parent->contentsX();
	int sy = m_masterTable->globalY(m_masterField);
	int rx = m_detailsTable->x() + m_parent->contentsX();
	int ry = m_detailsTable->globalY(m_detailsField);

	TQFont f( Kexi::smallFont( m_parent ) );
	TQFontMetrics fm(f);
	int side1x=0, side1y=sy - fm.height(), 
		sideNx=0, sideNy=ry - fm.height();
//! @todo details char can be also just a '1' for some cases
	TQChar sideNChar(0x221E); //infinity char
	uint sideNCharWidth = 2+2+ fm.width( sideNChar );
	TQChar side1Char('1');
	uint side1CharWidth = 2+2+ fm.width( side1Char );
	p->setBrush(p->pen().color());

	if(m_masterTable->x() < m_detailsTable->x())
	{
		//det. side
		p->drawLine(rx - sideNCharWidth, ry, rx, ry);
		TQPointArray pa(3);
		pa.setPoint(0, rx - 4, ry - 3);
		pa.setPoint(1, rx - 4, ry + 3);
		pa.setPoint(2, rx - 1, ry);
		p->drawPolygon(pa, true);
		
		//master side
		p->drawLine(sx, sy - 1, sx + side1CharWidth -1, sy - 1);
		p->drawLine(sx, sy, sx + side1CharWidth -1, sy);
		p->drawLine(sx, sy + 1, sx + side1CharWidth -1, sy + 1);

		side1x = sx;
//		side1y = sy - 7;

		sideNx = rx - sideNCharWidth - 1;
//		sideNy = ry - 6;

		TQPen pen(p->pen());
		if(m_selected)
		{
			TQPen pen(p->pen());
			pen.setWidth(2);
			p->setPen(pen);
		}

		p->drawLine(sx + side1CharWidth, sy, rx - sideNCharWidth, ry);

		if(m_selected)
		{
			TQPen pen(p->pen());
			pen.setWidth(1);
			p->setPen(pen);
		}

	}
	else
	{
		int lx = rx + m_detailsTable->width();
		int rx = sx - m_masterTable->width();

		//det. side
		p->drawLine(lx, ry, lx + sideNCharWidth, ry);
		TQPointArray pa(3);
		pa.setPoint(0, lx + 3, ry - 3);
		pa.setPoint(1, lx + 3, ry + 3);
		pa.setPoint(2, lx, ry);
		p->drawPolygon(pa, true);
		
//		p->drawLine(lx, ry, lx + 8, ry);
//		p->drawPoint(lx + 1, ry - 1);
//		p->drawPoint(lx + 1, ry + 1);
//		p->drawLine(lx + 2, ry - 2, lx + 2, ry + 2);

		//master side
		p->drawLine(rx - side1CharWidth +1, sy - 1, rx, sy - 1);
		p->drawLine(rx - side1CharWidth +1, sy + 1, rx, sy + 1);
		p->drawLine(rx - side1CharWidth +1, sy, rx, sy);

		side1x = rx - side1CharWidth;
//		side1y = sy - 7;

		sideNx = lx + 1;
//		sideNy = ry - 6;

		if(m_selected)
		{
			TQPen pen(p->pen());
			pen.setWidth(2);
			p->setPen(pen);
		}

		p->drawLine(lx + sideNCharWidth, ry, rx - side1CharWidth, sy);

		if(m_selected)
		{
			TQPen pen(p->pen());
			pen.setWidth(1);
			p->setPen(pen);
		}
	}

	p->drawText(side1x, side1y, side1CharWidth, fm.height(), TQt::AlignCenter, side1Char);
	p->drawText(sideNx, sideNy, sideNCharWidth, fm.height(), TQt::AlignCenter, sideNChar);
	//p->drawRect(TQRect(connectionRect().topLeft(), TQSize(50,50)));
//	p->drawPixmap(side1, TQPixmap(r1_xpm));
//	p->drawPixmap(sideN, TQPixmap(rn_xpm));
}

const TQRect
KexiRelationViewConnection::connectionRect()
{
	int sx = m_masterTable->x() + m_parent->contentsX();
	int rx = m_detailsTable->x() + m_parent->contentsX();
	int ry = m_detailsTable->globalY(m_detailsField);
	int sy = m_masterTable->globalY(m_masterField);

	int width, leftX, rightX;

	if(sx < rx)
	{
		leftX = sx;
		rightX = rx;
		width = m_masterTable->width();
	}
	else
	{
		leftX = rx;
		rightX = sx;
		width = m_detailsTable->width();
	}


	int dx = TQABS((leftX + width) - rightX);
	int dy = TQABS(sy - ry) + 2;

	int top = TQMIN(sy, ry);
	int left = leftX + width;


//	return TQRect(sx - 1, sy - 1, (rx + m_detailsTable->width()) - sx + 1, ry - sy + 1);
	TQRect rect(left - 150, top - 150, dx + 150, dy + 150);
//	kdDebug() << "KexiRelationViewConnection::connectionRect():" << m_oldRect << "," << rect << endl;
	
	m_oldRect = rect;

	return rect;
}

bool
KexiRelationViewConnection::matchesPoint(const TQPoint &p, int tolerance)
{
	TQRect we = connectionRect();

	if(!we.contains(p))
		return false;

	/** get our coordinats
	 *  you know what i mean the x1, y1 is the top point
	 *  and the x2, y2 is the bottom point
	 *  (quite tirvial :) although that was the entrace to the magic
	 *  gate...
	 */

	int sx = m_masterTable->x() + m_masterTable->width();
	int sy = m_masterTable->globalY(m_masterField);
	int rx = m_detailsTable->x();
	int ry = m_detailsTable->globalY(m_detailsField);

	int x1 = sx + 8;
	int y1 = sy;
	int x2 = rx - 8;
	int y2 = ry;

	if(sx > rx)
	{
		x1 = m_detailsTable->x() + m_detailsTable->width();
		x2 = m_masterTable->x();
		y2 = sy;
		y1 = ry;
	}

	/*
	  here we call pythagoras (the greek math geek :p)
	  see: http://w1.480.telia.com/%7Eu48019406/geekporn.gif if you don't know
	  how these people have got sex :)
	 */
	float mx = x2-x1;
	float my = y2-y1;
	float mag = sqrt(mx * mx + my * my);
	float u = (((p.x() - x1)*(x2 - x1))+((p.y() - y1)*(y2 - y1)))/(mag * mag);
	kdDebug() << "KexiRelationViewConnection::matchesPoint(): u: " << u << endl;

	float iX = x1 + u * (x2 - x1);
	float iY = y1 + u * (y2 - y1);
	kdDebug() << "KexiRelationViewConnection::matchesPoint(): px: " << p.x() << endl;
	kdDebug() << "KexiRelationViewConnection::matchesPoint(): py: " << p.y() << endl;
	kdDebug() << "KexiRelationViewConnection::matchesPoint(): ix: " << iX << endl;
	kdDebug() << "KexiRelationViewConnection::matchesPoint(): iy: " << iY << endl;

	float dX = iX - p.x();
	float dY = iY - p.y();

	kdDebug() << "KexiRelationViewConnection::matchesPoint(): dx: " << dX << endl;
	kdDebug() << "KexiRelationViewConnection::matchesPoint(): dy: " << dY << endl;

	float distance = sqrt(dX * dX + dY * dY);
	kdDebug() << "KexiRelationViewConnection::matchesPoint(): distance: " << distance << endl;

	if(distance <= tolerance)
		return true;

	return false;
}

TQString
KexiRelationViewConnection::toString() const
{
	TQString str;
/*! @todo what about query? */
	if (m_masterTable && m_masterTable->schema()->table()) {
		str += (TQString(m_masterTable->schema()->name()) + "." + m_masterField);
	}
	if (m_detailsTable && m_detailsTable->schema()->table()) {
		str += " - ";
		str += (TQString(m_detailsTable->schema()->name()) + "." + m_detailsField);
	}
	return str;
}
