#ifndef IPEFILEDATA_H
#define IPEFILEDATA_H

#include <vector>
#include <array>
#include <utility>
#include <stdexcept>

#include <QString>
#include <QFile>
#include <QByteArray>
#include <QRectF>
#include <QImage>

#include <QXmlStreamReader>
#include <QXmlStreamWriter>

class ProblemInstance;
class DrawingArea;

class InstanceReadError : public std::runtime_error
{
public:
    InstanceReadError(QString filePath, qint64 lineNumber, std::string&& msg)
        : std::runtime_error(std::move(msg)), _filePath(filePath), _lineNumber(lineNumber)
    {}
    ~InstanceReadError() throw() {}
    QString filePath() const { return _filePath; }
    qint64 lineNumber() const { return _lineNumber; }
private:
    QString _filePath;
    qint64 _lineNumber;
};

class InstanceWriteError : public std::runtime_error
{
public:
    InstanceWriteError(QString filePath, std::string&& msg)
        : std::runtime_error(std::move(msg)), _filePath(filePath)
    {}
    ~InstanceWriteError() throw() {}
    QString filePath() const { return _filePath; }
private:
    QString _filePath;
};

class IpeFileData
{
public:
    IpeFileData(ProblemInstance& problemInstance, QString const& filePath);

    IpeFileData(IpeFileData const&) = delete;
    IpeFileData& operator=(IpeFileData const&) = delete;

    IpeFileData(IpeFileData&& other);
    IpeFileData& operator=(IpeFileData&& other);

    void draw(DrawingArea* drawing) const;

    QString filePath() const { return _filePath; }
    void saveToFile(QString const& filepath);

private:
    void readFromFile();

    void readBitmapsAndStylesheets(QXmlStreamReader& reader, std::vector<QImage>& images);
    void readBitmap(QXmlStreamReader& reader, QXmlStreamWriter& writer, std::vector<QImage>& images);
    void readInstanceAndRouteAttributes(QXmlStreamReader& reader);

    void readFirstPage(QXmlStreamReader& reader, std::vector<QImage>&& images);
    void readRouteOrNetwork(QFile& file, int& lineNumber, QByteArray const& firstLine, bool isRoute);
    void readRoute(QFile& file, int& lineNumber, QByteArray const &firstLine) {
        readRouteOrNetwork(file, lineNumber, firstLine, true);
    }
    void readNetworkEdges(QFile& file, int& lineNumber, QByteArray const& firstLine) {
        readRouteOrNetwork(file, lineNumber, firstLine, false);
    }

    void readOtherPages(QXmlStreamReader& reader);

private:
    ProblemInstance const* _problemInstance;
    QString _filePath;
    std::array<QByteArray, 3> _ipeSection;
    std::vector< std::pair<QRectF, QImage> > _backgroundImages;
};

#endif // IPEFILEDATA_H
