//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      GUI/Model/Project/ProjectDocument.h
//! @brief     Defines class ProjectDocument.
//!
//! @homepage  http://www.bornagainproject.org
//! @license   GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
//  ************************************************************************************************

#ifndef BORNAGAIN_GUI_MODEL_PROJECT_PROJECTDOCUMENT_H
#define BORNAGAIN_GUI_MODEL_PROJECT_PROJECTDOCUMENT_H

#include "Wrap/WinDllMacros.h"
#include <QObject>
#include <QXmlStreamReader>

class DatafilesSet;
class InstrumentsSet;
class JobsSet;
class QIODevice;
class SamplesSet;
class SimulationOptionsItem;

//! Project document class handles all data related to the opened project
//! (sample, job, project specific settings).
//!
//! It also provides signaling regarding changes in the current document data.
//!
//! e.g. if project file is /home/users/development/Untitled/Untitled.ba
//! projectName()     - 'Untitled'
//! projectDir()      - '/home/users/development/Untitled
//! projectFileName() - '/home/users/development/Untitled/Untitled.ba'
class ProjectDocument : public QObject {
    Q_OBJECT
public:
    ProjectDocument();
    ~ProjectDocument();

    void clear();

    void setProjectDir(const QString& text);
    void setProjectName(const QString& text);
    void setProjectFullPath(const QString& fullPath);
    void saveProjectFileWithData(const QString& projectPullPath);
    void loadProjectFileWithData(const QString& projectPullPath);

    void setModified();
    bool isModified() const { return m_modified; }

    QString projectDir() const { return m_project_dir; }
    QString projectName() const { return m_project_name; }

    QString validProjectDir() const;
    QString projectFullPath() const;
    bool hasValidNameAndPath() const;

    uint viewId() const { return m_last_view_active; }
    void setViewId(uint id) { m_last_view_active = id; }

    const InstrumentsSet* instruments() const { return m_instruments.get(); };
    const SamplesSet* samples() const { return m_samples.get(); };
    const DatafilesSet* datafiles() const { return m_datafiles.get(); };
    const SimulationOptionsItem* simulationOptionsItem() const { return m_options.get(); };
    const JobsSet* jobs() const { return m_jobs.get(); };

    InstrumentsSet* instrumentsRW() { return m_instruments.get(); };
    SamplesSet* samplesRW() { return m_samples.get(); };
    DatafilesSet* datafilesRW() { return m_datafiles.get(); };
    SimulationOptionsItem* simulationOptionsRW() { return m_options.get(); };
    JobsSet* jobsRW() { return m_jobs.get(); };

    void writeTo(QXmlStreamWriter* w) const;
    void readFrom(QXmlStreamReader* r);

signals:
    void modifiedStateChanged();
    void sampleChanged();
    void documentAboutToReopen();
    void documentOpened();

private:
    void clearModified();

    void writeProject(QIODevice* device);
    void readProject(QIODevice* device);

    QString m_project_dir;
    QString m_project_name;
    bool m_modified;
    uint m_last_view_active;
    std::unique_ptr<InstrumentsSet> m_instruments;
    std::unique_ptr<SamplesSet> m_samples;
    std::unique_ptr<DatafilesSet> m_datafiles;
    std::unique_ptr<SimulationOptionsItem> m_options;
    std::unique_ptr<JobsSet> m_jobs;
};

BA_GUI_API_ extern std::unique_ptr<ProjectDocument> gDoc;

#endif // BORNAGAIN_GUI_MODEL_PROJECT_PROJECTDOCUMENT_H
