/**
    05Robot - serialization routines

    @author P.Kaczmarek,J.Tomczynski,T.Mankowski
    @version 1.0 2017
*/
#ifndef CXMLIO_H
#define CXMLIO_H
#include <QDataStream>
#include <QVector>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#include <QTextStream>

#include <QPropertyEditorWidget.h>
#include <QMetaObject>
#include <QMetaProperty>

/**
 * @brief Delivers XML file serialisation and deserialisation methods for modules
 */
class cXmlIO: public QObject
{
    Q_OBJECT
    /**
     * @brief Defines uniqe identifier for object in XML file
     */
    Q_PROPERTY(int xmlID READ getXmlID() WRITE setXmlID DESIGNABLE true USER true)
    int xmlID;
public:
    cXmlIO(int _xmlID=0,QObject* parent=nullptr);
    /**
     * @brief Generates key of XML entry (as name of the serialised class is)
     * @return
     */
    virtual QString sXmlKey()
    {
        return metaObject()->className();
    }

    /**
     * @brief serches th file for XML key corr to class name and fill class properties according to entries found
     * @param fileName
     * @param compareXmlID states if xmlID matters
     */
    virtual void findInXML(QString &fileName, bool compareXmlID=true);

    /**
     * @brief Writes XML entries to file. Can be overloaded to save additional data, apart from object properties
     * @param xml reference to XML file stream
     */
    virtual void writeXml(QXmlStreamWriter& xml);
    /**
     * @brief Called by findInXML. Reads XML entries. Has to be overloaded if additional data was written to file in object entry
     * @param xml reference to stream corresponding to object entry in XML
     */
    virtual void readXml(QXmlStreamReader& xml);

    virtual void writeCsvData(QXmlStreamWriter& stream, QString key, const QVector<QVector<double> > &s);
    virtual void writeCsvVector(QXmlStreamWriter &stream, QString key, const QVector<double > &s);
    virtual void readCsvData(QXmlStreamReader& stream, QVector<QVector<double> > &s);
    virtual void readCsvVector(QXmlStreamReader &stream, QVector<double> &s);
    virtual void write64BaseData(QXmlStreamWriter& stream, QString key, const QVector<QVector<double> > &s);
    virtual void read64BaseData(QXmlStreamReader &stream, QVector<QVector<double> > &s);
    
    template<typename T> void writeData(QXmlStreamWriter &stream, QString key, const T &data) {
        stream.writeStartElement(key);
        
        QString text;
        QTextStream tStream(&text,QIODevice::WriteOnly);
        
        tStream << data;
        
        stream.writeCDATA(text.toLatin1());
        stream.writeEndElement();
    }
    
    template<typename T> void readData(QXmlStreamReader &stream, T &data) {
        QString text = stream.readElementText();
        QTextStream tStream(&text,QIODevice::ReadOnly);
        
        tStream >> data;
    }
    

    int getXmlID() const;
    void setXmlID(int value);

    static void metaCopy(QObject *dest, QObject *src);
protected:
    void metaDataXmlReader(QXmlStreamReader &stream, QObject &obj, bool isUser=true);
    void metaDataXmlWriter(QXmlStreamWriter &stream, const QObject &obj, bool isUser=true);

};
QDataStream& operator<<( QDataStream& str, const QVector<QVector<double> > &s);
QDataStream& operator>>( QDataStream& str, QVector<QVector<double> > &s);
QTextStream& operator<<( QTextStream& str, const QVector<QVector<double> > &s);

#endif // CXMLIO_H
