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

#include "addattributedialog.h"
#include "cppsupportpart.h"
#include "backgroundparser.h"
#include "cppsupport_utils.h"

#include <kdevpartcontroller.h>

#include <codemodel.h>

#include <tdefiledialog.h>
#include <tdeparts/part.h>
#include <tdetexteditor/editinterface.h>
#include <klineedit.h>

#include <tqfileinfo.h>
#include <tqcombobox.h>
#include <tqlistview.h>
#include <tqcheckbox.h>
#include <tqpushbutton.h>
#include <tqtoolbutton.h>
#include <tqtextstream.h>

AddAttributeDialog::AddAttributeDialog( CppSupportPart* cppSupport, ClassDom klass,
                                        TQWidget* parent, const char* name, bool modal, WFlags fl )
: AddAttributeDialogBase( parent, name, modal, fl ), m_cppSupport( cppSupport ), m_klass( klass ), m_count( 0 )
{
	access->insertStringList( TQStringList() << "Public" << "Protected" << "Private" );
	
	storage->insertStringList( TQStringList() << "Normal" << "Static" );
	
	returnType->setAutoCompletion( true );
	returnType->insertStringList( TQStringList()
	                              << "void"
	                              << "char"
	                              << "wchar_t"
	                              << "bool"
	                              << "short"
	                              << "int"
	                              << "long"
	                              << "signed"
	                              << "unsigned"
	                              << "float"
	                              << "double" );
	
	returnType->insertStringList( typeNameList( m_cppSupport->codeModel() ) );
	
	updateGUI();
	addAttribute();
}

AddAttributeDialog::~AddAttributeDialog()
{}

void AddAttributeDialog::reject()
{
	TQDialog::reject();
}

void AddAttributeDialog::accept()
{
	m_cppSupport->partController()->editDocument( KURL( m_klass->fileName() ) );
	KTextEditor::EditInterface* editIface = dynamic_cast<KTextEditor::EditInterface*>( m_cppSupport->partController() ->activePart() );
	if ( !editIface )
	{
		/// @todo show messagebox
		TQDialog::accept();
		return ;
	}
	
	int line, column;
	m_klass->getEndPosition( &line, &column );
	
	// compute the insertion point map
	TQMap<TQString, TQPair<int, int> > points;
	TQStringList accessList;
	
	const VariableList variableList = m_klass->variableList();
	for ( VariableList::ConstIterator it = variableList.begin(); it != variableList.end(); ++it )
	{
		int varEndLine, varEndColumn;
		( *it ) ->getEndPosition( &varEndLine, &varEndColumn );
		TQString access = accessID( *it );
		TQPair<int, int> varEndPoint = qMakePair( varEndLine, varEndColumn );
		
		if ( !points.contains( access ) || points[ access ] < varEndPoint )
		{
			accessList.remove( access );
			accessList.push_back( access ); // move 'access' at the end of the list
			
			points[ access ] = varEndPoint;
		}
	}
	
	int insertedLine = 0;
	
	accessList += newAccessList( accessList );
	
	for ( TQStringList::iterator it = accessList.begin(); it != accessList.end(); ++it )
	{
		TQListViewItem* item = attributes->firstChild();
		while ( item )
		{
			TQListViewItem * currentItem = item;
			
			item = item->nextSibling();
			
			if ( currentItem->text( 0 ) != *it )
				continue;
			
			TQString access = ( *it ).lower();
			
			TQString str = variableDeclaration( currentItem );
			
			TQPair<int, int> pt;
			if ( points.contains( *it ) )
			{
				pt = points[ *it ];
			}
			else
			{
				str.prepend( access + ":\n" );
				points[ *it ] = qMakePair( line - 1, 0 );
				pt = points[ *it ]; // end of class declaration
			}
			
			editIface->insertText( pt.first + insertedLine + 1, 0 /*pt.second*/, str );
			insertedLine += str.contains( TQChar( '\n' ) );
		}
	}
	
	m_cppSupport->backgroundParser() ->addFile( m_klass->fileName() );
	
	TQDialog::accept();
}

TQString AddAttributeDialog::variableDeclaration( TQListViewItem* item ) const
{
	TQString str;
	TQTextStream stream( &str, IO_WriteOnly );
	TQString ind;
	ind.fill( TQChar( ' ' ), 4 );
	
	stream << ind;
	if ( item->text( 1 ) == "Static" )
		stream << "static ";
	stream << item->text( 2 ) << " " << item->text( 3 );
	stream << ";\n";
	
	return str;
}


void AddAttributeDialog::updateGUI()
{
	bool enable = attributes->selectedItem() != 0;
	
	returnType->setEnabled( enable );
	declarator->setEnabled( enable );
	access->setEnabled( enable );
	storage->setEnabled( enable );
	
	deleteAttributeButton->setEnabled( enable );
	
	if ( enable )
	{
		TQListViewItem * item = attributes->selectedItem();
		item->setText( 0, access->currentText() );
		item->setText( 1, storage->currentText() );
		item->setText( 2, returnType->currentText() );
		item->setText( 3, declarator->text() );
	}
}

void AddAttributeDialog::addAttribute()
{
	TQListViewItem * item = new TQListViewItem( attributes, "Protected", "Normal",
	                                          "int", TQString( "attribute_%1" ).arg( ++m_count ) );
	attributes->setCurrentItem( item );
	attributes->setSelected( item, true );
	
	returnType->setFocus();
}

void AddAttributeDialog::deleteCurrentAttribute()
{
	delete( attributes->currentItem() );
}

void AddAttributeDialog::currentChanged( TQListViewItem* item )
{
	if ( item )
	{
		TQString _access = item->text( 0 );
		TQString _storage = item->text( 1 );
		TQString _returnType = item->text( 2 );
		TQString _declarator = item->text( 3 );
		
		access->setCurrentText( _access );
		storage->setCurrentText( _storage );
		returnType->setCurrentText( _returnType );
		declarator->setText( _declarator );
	}
	
	updateGUI();
}

TQStringList AddAttributeDialog::newAccessList( const TQStringList& accessList ) const
{
	TQStringList newAccessList;
	
	TQListViewItem* item = attributes->firstChild();
	while ( item )
	{
		TQListViewItem * currentItem = item;
		
		item = item->nextSibling();
		
		TQString access = currentItem->text( 0 );
		if ( !( accessList.contains( access ) || newAccessList.contains( access ) ) )
			newAccessList.push_back( access );
	}
	
	return newAccessList;
}

TQString AddAttributeDialog::accessID( VariableDom var ) const
{
	switch ( var->access() )
	{
	case CodeModelItem::Public:
		return TQString::fromLatin1( "Public" );
		
	case CodeModelItem::Protected:
		return TQString::fromLatin1( "Protected" );
		
	case CodeModelItem::Private:
		return TQString::fromLatin1( "Private" );
	}
	
	return TQString();
}

#include "addattributedialog.moc" 
