/***************************************************************************
*   Copyright (C) 2004 by Alexander Dymo                                  *
*   adymo@mksat.net                                                       *
*   Portions Copyright (C) 2003 Roberto Raggi (roberto@kdevelop.org)      *
*                                                                         *
*   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.,                                       *
*   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.             *
***************************************************************************/
#include "tqtdesignercppintegration.h"

#include <tqpair.h>
#include <tqregexp.h>

#include <tdelocale.h>
#include <kdebug.h>
#include <tdemessagebox.h>
#include <kurl.h>
#include <tdetexteditor/editinterface.h>
#include <tdetexteditor/view.h>
#include <tdetexteditor/viewcursorinterface.h>

#include <domutil.h>
#include <kdevpartcontroller.h>
#include <kdevcreatefile.h>

#include "backgroundparser.h"
#include "cppsupportpart.h"
#include "codemodel_utils.h"
#include "implementationwidget.h"

QtDesignerCppIntegration::QtDesignerCppIntegration( KDevLanguageSupport *part,
	                                                ImplementationWidget *impl )
: QtDesignerIntegration( part, impl, true, 0 )
{}

void QtDesignerCppIntegration::addFunctionToClass( KInterfaceDesigner::Function function, ClassDom klass )
{
	m_part->partController() ->editDocument( KURL( klass->fileName() ) );
	KTextEditor::EditInterface* editIface = dynamic_cast<KTextEditor::EditInterface*>( m_part->partController() ->activePart() );
	if ( !editIface )
	{
		/// @todo show messagebox
		//        TQDialog::accept();
		return ;
	}

	int line, column;
	klass->getEndPosition( &line, &column );

	// compute the insertion point map
	TQMap<TQString, TQPair<int, int> > points;

	const FunctionList functionList = klass->functionList();
	for ( FunctionList::ConstIterator it = functionList.begin(); it != functionList.end(); ++it )
	{
		int funEndLine, funEndColumn;
		( *it ) ->getEndPosition( &funEndLine, &funEndColumn );
		TQString access = accessID( *it );
		TQPair<int, int> funEndPoint = tqMakePair( funEndLine, funEndColumn );

		if ( !points.contains( access ) || points[ access ] < funEndPoint )
		{
			points[ access ] = funEndPoint;
		}
	}

	int insertedLine = 0;

	TQString access = function.access + ( function.type == KInterfaceDesigner::ftTQtSlot ? " slots" : "" );

	TQString str = function.returnType + " " + function.function;
	if ( function.specifier == "virtual" )
		str = "virtual " + str;
	else if ( function.specifier == "pure virtual" )
		str = "virtual " + str + " = 0";
	else if ( function.specifier == "static" )
		str = "static " + str;
	str += ";\n";
	str = "    " + str;

	TQPair<int, int> pt;
	if ( points.contains( access ) )
	{
		pt = points[ access ];
	}
	else
	{
		str.prepend( access + ":\n" );
		points[ access ] = tqMakePair( line - 1, 0 );
		pt = points[ access ]; // end of class declaration
	}

	editIface->insertText( pt.first + insertedLine + 1, 0 /*pt.second*/, str );
	insertedLine += str.contains( TQChar( '\n' ) );

	CppSupportPart *cppPart = dynamic_cast<CppSupportPart *>( m_part );
	cppPart->backgroundParser() ->addFile( klass->fileName() );

	if ( function.specifier == "pure virtual" )
		return ;


	//implementation
	TQString stri = function.returnType + " " + klass->name() + "::" + function.function;
	if ( function.specifier == "static" )
		stri = "static " + stri;
	stri += "\n{\n}\n";
	stri = "\n" + stri;

	TQFileInfo fi( klass->fileName() );
	TQString implementationFile = fi.absFilePath();
	implementationFile.replace( ".h", ".cpp" );
	
	TQFileInfo fileInfo( implementationFile );
	if ( !TQFile::exists( fileInfo.absFilePath() ) )
	{
		if ( KDevCreateFile * createFileSupp = m_part->extension<KDevCreateFile>( "TDevelop/CreateFile" ) )
			createFileSupp->createNewFile( fileInfo.extension(), fileInfo.dirPath( true ), fileInfo.fileName() );
	}
	
	m_part->partController() ->editDocument( KURL( implementationFile ) );
	editIface = dynamic_cast<KTextEditor::EditInterface*>( m_part->partController() ->activePart() );
	if ( !editIface )
		return ;
	
	int atLine = 0, atColumn = 0;
	TranslationUnitAST *translationUnit = 0;
	ParsedFilePointer p = cppPart->backgroundParser() ->translationUnit( implementationFile );
	if( p ) translationUnit = *p;
	if ( translationUnit )
	{
		translationUnit->getEndPosition( &atLine, &atColumn );
		kdDebug() << "atLine: " << atLine << endl;
		stri = "\n" + stri;
	}
	else
	{
		atLine = editIface->numLines();
		line = editIface->numLines();
		while ( line > 0 )
		{
			if ( editIface->textLine( line ).isEmpty() )
			{
				--line;
				continue;
			}
			else
			{
				if ( editIface->textLine( line ).contains( TQRegExp( ".*#include .*\\.moc.*" ) ) )
					atLine = line;
				break;
			}
		}
	kdDebug() << "atLine (2): " << atLine << endl;
		atColumn = 0;
	}
	
	//    editIface->insertLine( atLine + 1, TQString::fromLatin1("") );
	kdDebug() << "at line in intg: " << atLine << " atCol: " << atColumn << endl;
	kdDebug() << "text: " << stri << endl;
	editIface->insertText( atLine, atColumn, stri );
	KTextEditor::View *activeView = dynamic_cast<KTextEditor::View*>( m_part->partController() ->activePart() ->widget() );
	if ( activeView )
	{
		KTextEditor::ViewCursorInterface * cursor = dynamic_cast<KTextEditor::ViewCursorInterface*>( activeView );
		if ( cursor )
			cursor->setCursorPositionReal( atLine + 3, 1 );
	}
	
	cppPart->backgroundParser() ->addFile( implementationFile );
}

TQString QtDesignerCppIntegration::accessID( FunctionDom fun ) const
{
	if ( fun->isSignal() )
		return TQString::fromLatin1( "signals" );

	switch ( fun->access() )
	{
	case CodeModelItem::Public:
		if ( fun->isSlot() )
			return TQString::fromLatin1( "public slots" );
		return TQString::fromLatin1( "public" );

	case CodeModelItem::Protected:
		if ( fun->isSlot() )
			return TQString::fromLatin1( "protected slots" );
		return TQString::fromLatin1( "protected" );

	case CodeModelItem::Private:
		if ( fun->isSlot() )
			return TQString::fromLatin1( "private slots" );
		return TQString::fromLatin1( "private" );
	}

	return TQString();
}

void QtDesignerCppIntegration::processImplementationName( TQString &name )
{
	name.replace( ".h", ".cpp" );
}

#include "tqtdesignercppintegration.moc"
