/***************************************************************************
    File                 : Folder.cpp
    Project              : SciDAVis
    Description          : Folder in a project
    --------------------------------------------------------------------
    Copyright            : (C) 2007 Tilman Benkert (thzs*gmx.net)
    Copyright            : (C) 2007 Knut Franke (knut.franke*gmx.de)
                           (replace * with @ in the email addresses)

 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *  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 "core/Project.h"
#include "core/future_Folder.h"
#include "lib/XmlStreamReader.h"
#include "core/column/Column.h"

#include <QIcon>
#include <QApplication>
#include <QStyle>
#include <QXmlStreamWriter>
#include <QPluginLoader>
#include <QtDebug>

namespace future {
Folder::Folder(const QString &name) : AbstractAspect(name) { }

Folder::~Folder() { }

QIcon Folder::icon() const
{
    QIcon result;
    result.addFile(":/folder_closed.xpm", QSize(), QIcon::Normal, QIcon::Off);
    result.addFile(":/folder_open.xpm", QSize(), QIcon::Normal, QIcon::On);
    return result;
}

QMenu *Folder::createContextMenu() const
{
    if (project())
        return project()->createFolderContextMenu(this);
    return 0;
}

void Folder::save(QXmlStreamWriter *writer) const
{
    writer->writeStartElement("folder");
    writeBasicAttributes(writer);
    writeCommentElement(writer);

    int child_count = childCount();
    for (int i = 0; i < child_count; i++) {
        writer->writeStartElement("child_aspect");
        child(i)->save(writer);
        writer->writeEndElement(); // "child_aspect"
    }
    writer->writeEndElement(); // "folder"
}

bool Folder::load(XmlStreamReader *reader)
{
    if (reader->isStartElement() && reader->name() == "folder") {
        setComment("");
        removeAllChildAspects();

        if (!readBasicAttributes(reader))
            return false;

        // read child elements
        while (!reader->atEnd()) {
            reader->readNext();

            if (reader->isEndElement())
                break;

            if (reader->isStartElement()) {
                if (reader->name() == "comment") {
                    if (!readCommentElement(reader))
                        return false;
                } else if (reader->name() == "child_aspect") {
                    if (!readChildAspectElement(reader))
                        return false;
                } else // unknown element
                {
                    reader->raiseWarning(tr("unknown element '%1'").arg(reader->name().toString()));
                    if (!reader->skipToEndElement())
                        return false;
                }
            }
        }
    } else // no folder element
        reader->raiseError(tr("no folder element found"));

    return !reader->hasError();
}

bool Folder::readChildAspectElement(XmlStreamReader *reader)
{
    bool loaded = false;
    Q_ASSERT(reader->isStartElement() && reader->name() == "child_aspect");

    if (!reader->skipToNextTag())
        return false;
    if (reader->isEndElement() && reader->name() == "child_aspect")
        return true; // empty element tag
    QString element_name = reader->name().toString();
    if (element_name == "folder") {
        Folder *folder = new Folder(tr("Folder %1").arg(1));
        if (!folder->load(reader)) {
            delete folder;
            return false;
        }
        addChild(folder);
        loaded = true;
    } else if (element_name == "column") {
        Column *column = new Column(tr("Column %1").arg(1), SciDAVis::ColumnMode::Text);
        if (!column->load(reader)) {
            delete column;
            return false;
        }
        addChild(column);
        loaded = true;
    } else {
        foreach (QObject *plugin, QPluginLoader::staticInstances()) {
            XmlElementAspectMaker *maker = qobject_cast<XmlElementAspectMaker *>(plugin);
            if (maker && maker->canCreate(element_name)) {
                AbstractAspect *aspect = maker->createAspectFromXml(reader);
                if (aspect) {
                    addChild(aspect);
                    loaded = true;
                    break;
                } else {
                    reader->raiseError(
                            tr("creation of aspect from element '%1' failed").arg(element_name));
                    return false;
                }
            }
        }
    }
    if (!loaded) {
        reader->raiseWarning(tr("no plugin to load element '%1' found").arg(element_name));
        if (!reader->skipToEndElement())
            return false;
    }
    if (!reader->skipToNextTag())
        return false;
    Q_ASSERT(reader->isEndElement() && reader->name() == "child_aspect");
    return !reader->hasError();
}

} // namespace
