/*
  TDevelop Autotools Support
  Copyright (c) 2005 by Matt Rogers <mattr@kde.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 <tqdir.h>
#include <tqglobal.h>
#include <tqmap.h>
#include <tqregexp.h>
#include <tqstring.h>
#include <tqvaluelist.h>

#include <kdebug.h>

#include <autotoolsast.h>
#include <autotoolsdriver.h>

#include "makefilehandler.h"

typedef TQValueList<AutoTools::AST*> ASTList;

class MakefileHandler::Private
{
public:
    TQMap<TQString, AutoTools::ProjectAST*> projects;
    TQMap<TQString, TQString> folderToFileMap;
};

MakefileHandler::MakefileHandler()
{
    d = new MakefileHandler::Private;
}

MakefileHandler::~MakefileHandler()
{
    delete d;
}

void MakefileHandler::parse( const TQString& folder, bool recursive )
{
    //look for either Makefile.am.in, Makefile.am, or Makefile.in, in that order
    AutoTools::ProjectAST* ast;
    int ret = -1;
    TQString filePath = folder + "/Makefile.am.in";
    if ( TQFile::exists( filePath ) )
        ret = AutoTools::Driver::parseFile( filePath, &ast );
    else
    {
        filePath = folder + "/Makefile.am";
        if ( TQFile::exists( filePath ) )
            ret = AutoTools::Driver::parseFile( filePath, &ast );
        else
        {
            filePath = folder + "/Makefile.in";
            if ( TQFile::exists( filePath ) )
                ret = AutoTools::Driver::parseFile( filePath, &ast );
            else
                kdDebug(9020) << k_funcinfo << "no appropriate file to parse in "
                              << folder << endl;
        }
    }

    if ( ret != 0 )
    {
        return;
    }

    kdDebug(9020) << k_funcinfo << filePath << " was parsed correctly. Adding information" << endl;
    Q_ASSERT( ast != 0 );
    d->projects[filePath] = ast;
    d->folderToFileMap[folder] = filePath;

    if ( recursive && ast && ast->hasChildren() )
    {
        TQValueList<AutoTools::AST*> astChildList = ast->children();
        TQValueList<AutoTools::AST*>::iterator it(astChildList.begin()), clEnd(astChildList.end());
        for ( ; it != clEnd; ++it )
        {
            if ( (*it)->nodeType() == AutoTools::AST::AssignmentAST )
            {
                AutoTools::AssignmentAST* assignment = static_cast<AutoTools::AssignmentAST*>( (*it) );
                if ( assignment->scopedID == "SUBDIRS"  )
                {
                    TQString list = assignment->values.join( TQString::null );
                    list.simplifyWhiteSpace();
                    kdDebug(9020) << k_funcinfo << "subdirs is " << list << endl;
                    TQStringList subdirList = TQStringList::split( " ",  list );
                    TQStringList::iterator vit = subdirList.begin();
                    for ( ; vit != subdirList.end(); ++vit )
                    {
                        TQString realDir = ( *vit );
                        if ( realDir.startsWith( "\\" ) )
                            realDir.remove( 0, 1 );

                        realDir = realDir.stripWhiteSpace();
                        if ( realDir != "." && realDir != ".." && !realDir.isEmpty() )
                        {
                            if ( isVariable( realDir ) )
                            {
                                kdDebug(9020) << k_funcinfo << "'" << realDir << "' is a variable" << endl;
                                realDir = resolveVariable( realDir, ast );
                            }

                            kdDebug(9020) << k_funcinfo << "Beginning parsing of '" << realDir << "'" << endl;
                            parse( folder + '/' + realDir, recursive );
                        }
                    }
                }
            }
        }
    }
}

AutoTools::ProjectAST* MakefileHandler::astForFolder( const TQString& folderPath )
{
    if ( d->folderToFileMap.contains( folderPath ) )
    {
        TQString filePath = d->folderToFileMap[folderPath];
        return d->projects[filePath];
    }
    else
        return 0;
}

bool MakefileHandler::isVariable( const TQString& item ) const
{
    if ( item.contains( TQRegExp( "(\\$\\([a-zA-Z0-9_-]*\\)|@[a-zA-Z0-9_-]*@)" ) ) )
        return true;
    else
        return false;
}

TQString MakefileHandler::resolveVariable( const TQString& variable, AutoTools::ProjectAST* ast )
{
    if ( !ast )
        return variable;

    kdDebug(9020) << k_funcinfo << "attempting to resolve '" << variable << "'"<< endl;
    ASTList childList = ast->children();
    ASTList::iterator it( childList.begin() ), clEnd( childList.end() );
    for ( ; it != clEnd; ++it )
    {
        if ( ( *it )->nodeType() == AutoTools::AST::AssignmentAST )
        {
            AutoTools::AssignmentAST* assignment = static_cast<AutoTools::AssignmentAST*>( ( *it ) );
            if ( variable.find( assignment->scopedID ) != -1 )
            {
                kdDebug(9020) << k_funcinfo << "Resolving variable '" << variable << "' to '"
                              << assignment->values.join( TQString::null ).stripWhiteSpace() << "'" << endl;
                return assignment->values.join( TQString::null ).stripWhiteSpace();
            }
        }
    }

    return variable;
}
