//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2006-2007 Torsten Rahn <tackat@kde.org>
// Copyright 2007      Inge Wallin  <ingwa@kde.org>
//

#include "FileManager.h"

#include <QtCore/QDir>
#include <QtCore/QFileInfo>

#include "FileLoader.h"
#include "FileViewModel.h"
#include "KmlFileViewItem.h"
#include "MarbleDebug.h"
#include "MarbleDataFacade.h"
#include "MarbleGeometryModel.h"

#include "GeoDataDocument.h"


using namespace Marble;

namespace Marble
{
class FileManagerPrivate
{
public:
    FileManagerPrivate( )
        : m_datafacade( 0 )
    {
    }

    MarbleDataFacade* m_datafacade;
    QList<FileLoader*> m_loaderList;
    QStringList m_pathList;
    QList < AbstractFileViewItem* > m_fileItemList;
};
}

FileManager::FileManager( QObject *parent )
    : QObject( parent )
    , d( new FileManagerPrivate() )
{
}


FileManager::~FileManager()
{
    foreach ( FileLoader *loader, d->m_loaderList ) {
        if ( loader ) {
            loader->wait();
        }
    }

    foreach ( AbstractFileViewItem *file, d->m_fileItemList ) {
        delete file;
    }

    delete d;
}

void FileManager::setDataFacade( MarbleDataFacade *facade )
{
    d->m_datafacade = facade;
    d->m_datafacade->fileViewModel()->setFileManager( this );
}

MarbleDataFacade *FileManager::dataFacade()
{
    return d->m_datafacade;
}

QStringList FileManager::containers() const
{
    QStringList retList;
    for ( int line = 0; line < d->m_fileItemList.count(); ++line ) {
        retList << d->m_fileItemList.at( line )->name();
    }
    return retList + d->m_pathList;
}

QString FileManager::toRegularName( QString name )
{
    QFileInfo fileinfo( name );
    return fileinfo.completeBaseName();
}

void FileManager::addFile( const QString& filepath )
{
    QString regularName = toRegularName( filepath );
    if ( !containers().contains( regularName ) ) {
        mDebug() << "adding container:" << regularName;
        FileLoader* loader = new FileLoader( this, filepath );
        appendLoader( loader );
        d->m_pathList.append( filepath );
    }
}

void FileManager::addData( const QString &name, const QString &data )
{
    FileLoader* loader = new FileLoader( this, data, name );
    appendLoader( loader );
}

void FileManager::appendLoader( FileLoader *loader )
{
    connect( loader, SIGNAL( loaderFinished( FileLoader* ) ),
             this, SLOT( cleanupLoader( FileLoader* ) ) );

    connect( loader, SIGNAL( newGeoDataDocumentAdded( GeoDataDocument* ) ),
             this, SLOT( addGeoDataDocument( GeoDataDocument* ) ) );

    d->m_loaderList.append( loader );
    loader->start();
}

void FileManager::removeFile( const QString& key )
{
    for ( int i = 0; i < d->m_fileItemList.size(); ++i ) {
        if ( toRegularName( key ) == toRegularName( d->m_fileItemList.at(i)->name() ) ) {
            closeFile( i );
            break;
        }
    }
}

void FileManager::addFile ( AbstractFileViewItem * item )
{
    mDebug() << "FileManager::addFile";
    d->m_fileItemList.append( item );
    emit fileAdded( d->m_fileItemList.indexOf( item ) );
}

void FileManager::saveFile( int index )
{
    if ( index < d->m_fileItemList.size() ) {
        d->m_fileItemList.at( index )->saveFile();
    }
}

void FileManager::closeFile( int index )
{
    mDebug() << "FileManager::closeFile";
    if ( index < d->m_fileItemList.size() ) {
        emit fileRemoved( index );
        KmlFileViewItem *file =
                static_cast<KmlFileViewItem*>( d->m_fileItemList.at( index ));
        if ( file ) {
            MarbleGeometryModel *geometryModel = d->m_datafacade->geometryModel();
            if ( geometryModel->geoDataRoot() == file->document() ) {
                geometryModel->setGeoDataRoot( 0 );
            }
        }
        delete d->m_fileItemList.at( index );
        d->m_fileItemList.removeAt( index );
    }
}

int FileManager::size() const
{
    return d->m_fileItemList.size();
}

AbstractFileViewItem * FileManager::at( int index )
{
    if ( index < d->m_fileItemList.size() ) {
        return d->m_fileItemList.at( index );
    }
    return 0;
}

void FileManager::addGeoDataDocument( GeoDataDocument* document )
{
    KmlFileViewItem* item = new KmlFileViewItem( *this, *document );
    addFile( item );

    // now get the document that will be preserved throughout the life time
    GeoDataDocument* doc = item->document();
    // remove the hashes in front of the styles.
    QVector<GeoDataFeature>::Iterator end = doc->end();
    QVector<GeoDataFeature>::Iterator itr = doc->begin();
    for ( ; itr != end; ++itr ) {
        // use *itr (or itr.value()) here
        QString styleUrl = itr->styleUrl().remove('#');
        itr->setStyle( &doc->style( styleUrl ) );
    }

    // do not set this file if it only contains points
    if ( doc->isVisible() && d->m_datafacade->geometryModel() )
        d->m_datafacade->geometryModel()->setGeoDataRoot( doc );
}

void FileManager::cleanupLoader( FileLoader* loader )
{
    d->m_loaderList.removeAll( loader );
    if ( loader->isFinished() ) {
        d->m_pathList.removeAll( loader->path() );
        delete loader;
    }
}

#include "FileManager.moc"
