/***************************************************************************
 *   Copyright (C) 2002 by 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.                                   *
 *                                                                         *
 ***************************************************************************/

#include "ast_utils.h"
#include "ast.h"

#include <tqstringlist.h>
#include <tqregexp.h>

#include <tdelocale.h>
#include <kdebug.h>
#include <tdeapplication.h>

AST* findNodeAt( AST* node, int line, int column )
{
    // kdDebug(9007) << "findNodeAt(" << node << ")" << endl;

    if( !node )
	return 0;

    int startLine, startColumn;
    int endLine, endColumn;

    node->getStartPosition( &startLine, &startColumn );
    node->getEndPosition( &endLine, &endColumn );

    if( (line > startLine || (line == startLine && column >= startColumn)) &&
        (line < endLine || (line == endLine && column < endColumn)) ){

        TQPtrList<AST> children = node->children();
	TQPtrListIterator<AST> it( children );
	while( it.current() ){
	    AST* a = it.current();
	    ++it;

	    AST* r = findNodeAt( a, line, column );
	    if( r )
		return r;
	}

	return node;
    }

    return 0;
}

void scopeOfNode( AST* ast, TQStringList& scope )
{
    if( !ast )
	return;

    if( ast->parent() )
	scopeOfNode( ast->parent(), scope );

    TQString s;
    switch( ast->nodeType() )
    {
    case NodeType_ClassSpecifier:
        if( ((ClassSpecifierAST*)ast)->name() ){
	    s = ((ClassSpecifierAST*)ast)->name()->text();
	    s = s.isEmpty() ? TQString::fromLatin1("<unnamed>") : s;
	    scope.push_back( s );
	}
	break;

    case NodeType_Namespace:
    {
        AST* namespaceName = ((NamespaceAST*)ast)->namespaceName();
	s = namespaceName ? namespaceName->text() : TQString::fromLatin1("<unnamed>");
	scope.push_back( s );
    }
    break;

    case NodeType_FunctionDefinition:
    {
	FunctionDefinitionAST* funDef = static_cast<FunctionDefinitionAST*>( ast );
	DeclaratorAST* d = funDef->initDeclarator()->declarator();
	
	// hotfix for bug #68726
	if ( !d->declaratorId() )
		break;
	
	TQPtrList<ClassOrNamespaceNameAST> l = d->declaratorId()->classOrNamespaceNameList();
	TQPtrListIterator<ClassOrNamespaceNameAST> nameIt( l );
	while( nameIt.current() ){
	    AST* name = nameIt.current()->name();
	    scope.push_back( name->text() );
	
	    ++nameIt;
	}
    }
    break;

    default:
	break;
    }
}


TQString typeSpecToString( TypeSpecifierAST* typeSpec )  /// @todo remove
{
    if( !typeSpec )
        return TQString();

    return typeSpec->text().replace( TQRegExp(" :: "), "::" );
}

TQString declaratorToString( DeclaratorAST* declarator, const TQString& scope, bool skipPtrOp )
{
   if( !declarator )
       return TQString();

   TQString text;

   if( !skipPtrOp ){
       TQPtrList<AST> ptrOpList = declarator->ptrOpList();
       for( TQPtrListIterator<AST> it(ptrOpList); it.current(); ++it ){
	  text += it.current()->text();
       }
       text += ' ';
   }

   text += scope;

   if( declarator->subDeclarator() )
       text += TQString::fromLatin1("(") + declaratorToString(declarator->subDeclarator()) + TQString::fromLatin1(")");

   if( declarator->declaratorId() )
       text += declarator->declaratorId()->text();

   TQPtrList<AST> arrays = declarator->arrayDimensionList();
   TQPtrListIterator<AST> it( arrays );
   while( it.current() ){
       text += "[]";
       ++it;
   }

   if( declarator->parameterDeclarationClause() ){
       text += "( ";

       ParameterDeclarationListAST* l = declarator->parameterDeclarationClause()->parameterDeclarationList();
       if( l != 0 ){
           TQPtrList<ParameterDeclarationAST> params = l->parameterList();
	   TQPtrListIterator<ParameterDeclarationAST> it( params );

           while( it.current() ){
	       TQString type = typeSpecToString( it.current()->typeSpec() );
	       text += type;
	       if( !type.isEmpty() )
		   text += ' ';
               text += declaratorToString( it.current()->declarator() );

               ++it;

	       if( it.current() )
	           text += ", ";
           }
       }

       text += " )";

       if( declarator->constant() != 0 )
           text += " const";
   }

   return text.replace( TQRegExp(" :: "), "::" ).simplifyWhiteSpace();
}

