#include "cxmlio.h"
#include "QPropertyEditorWidget.h"
#include <QStringList>
#include <QDebug>
#include <QFile>
int cXmlIO::getXmlID() const
{
    return xmlID;
}

void cXmlIO::setXmlID(int value)
{
    xmlID = value;
}

cXmlIO::cXmlIO(int _xmlID, QObject *parent):xmlID(_xmlID),QObject(parent)
{

}
void cXmlIO::metaCopy(QObject *dest,QObject* src)
{
    for (int i=0;i<src->metaObject()->propertyCount();++i)
    {
        if((src->metaObject()->property(i)).isUser(src))
        {
            int idx=dest->metaObject()->indexOfProperty(src->metaObject()->property(i).name());
            if(idx>0)
                dest->metaObject()->property(i).write(dest,src->metaObject()->property(i).read(src));
            //stream.writeAttribute(,obj.metaObject()->property(i).read(&obj).value<QString>());

        }
    }
}

void cXmlIO::metaDataXmlWriter(QXmlStreamWriter &stream,const QObject &obj,bool isUser)
{
    for (int i=0;i<obj.metaObject()->propertyCount();++i)
    {
        if((obj.metaObject()->property(i)).isUser(&obj)||!isUser)
        {
            stream.writeAttribute(obj.metaObject()->property(i).name(),obj.metaObject()->property(i).read(&obj).value<QString>());

        }
    }

}
void cXmlIO::metaDataXmlReader(QXmlStreamReader &stream,QObject &obj,bool isUser)
{	QVariant var;
    QXmlStreamAttributes attributes = stream.attributes();
    for (int i=0;i<obj.metaObject()->propertyCount();++i)
    {
        if((obj.metaObject()->property(i)).isUser(&obj)||!isUser)
        {
            if(attributes.hasAttribute(obj.metaObject()->property(i).name()))
            {
                var=QVariant(attributes.value(obj.metaObject()->property(i).name()).toString());

                bool to_int_ok = 0;
                if(obj.metaObject()->property(i).isEnumType()) {
                    obj.setProperty(qPrintable(obj.metaObject()->property(i).name()), obj.metaObject()->property(i).enumerator().  key(var.toInt(&to_int_ok)));
                    if (!to_int_ok) {
                        obj.setProperty(qPrintable(obj.metaObject()->property(i).name()), obj.metaObject()->property(i).enumerator().keyToValue(var.toString().toLatin1().constData()));
                    }
                } else {
                    obj.metaObject()->property(i).write(&obj,var);
                }
            }

        }
    }

}

QDataStream& operator<<( QDataStream& str, const QVector<QVector<double> > &s)
{

    str<<s.size();

    for(int i=0;i<s.size();i++)
    {
        str<<s[i].size();
        for(int j=0;j<s[i].size();j++)
        {
            str<<(double)(s[i][j]);
        }

    }
    //str<<s;
    return str;
}

QDataStream& operator>>( QDataStream& str, QVector<QVector<double> > &s)
{
    int size;
    str>>size;
    s.resize(size);
    if(size!=0)
    {

        for(int i=0;i<size;i++)
        {
            int size2;
            str>>size2;
            s[i].resize(size2);
            for(int j=0;j<size2;j++)
            {
                str>>(s[i][j]);
            }

        }
    }
    return str;
}

void cXmlIO::writeXml(QXmlStreamWriter &xml)
{

    xml.writeStartElement(sXmlKey());
    //TODO: XML data
    metaDataXmlWriter(xml,*this);

    xml.writeEndElement();

}

void cXmlIO::readXml(QXmlStreamReader &xml)
{
    metaDataXmlReader(xml,*this);
}

void cXmlIO::findInXML(QString &fileName,bool compareXmlID)
{    
    QFile file;
    file.setFileName(fileName);
    if (file.open(QIODevice::ReadOnly))
    {

        file.seek(0);
        QXmlStreamReader stream(&file);
        while(!(stream.atEnd()))
        {

            if (stream.readNextStartElement()){

                if(stream.name() == sXmlKey())
                {
                    if(compareXmlID)
                    {
                        QXmlStreamAttributes attributes = stream.attributes();
                        if(attributes.hasAttribute("xmlID"))
                        {
                            int id = attributes.value("xmlID").toString().toInt();
                            if(id==xmlID)
                            {
                                readXml(stream);
                                break;
                            }
                        }
                    }
                    else
                    {
                        readXml(stream);
                        break;
                    }
                }

            }
            // stream.readNext();
        }
        file.close();
    }
}

void cXmlIO::writeCsvData(QXmlStreamWriter &stream, QString key, const QVector<QVector<double> > &s)
{
    stream.writeStartElement(key);

    QString text;
    QTextStream tStream(&text,QIODevice::WriteOnly);

    tStream <<s;

    stream.writeCDATA(text.toLatin1());
    stream.writeEndElement();
}

void cXmlIO::writeCsvVector(QXmlStreamWriter &stream, QString key, const QVector<double > &s)
{
    stream.writeStartElement(key);

    QString text;
    QTextStream tStream(&text,QIODevice::WriteOnly);

    //tStream<<s.size()<<':';
    for(int j=0;j<s.size();j++)
    {
        tStream<<(double)(s[j]);
        if(j<s.size()-1)
        {
            tStream<<",";
        }
    }

    stream.writeCDATA(text.toLatin1());
    stream.writeEndElement();
}

void cXmlIO::readCsvData(QXmlStreamReader &stream, QVector<QVector<double> > &s)
{
    QString text = stream.readElementText();
    QStringList list = text.split('\n');
    for(int i=0;i<list.size();i++)
    {
        QString el=list[i];
        QStringList row = el.split(',');
        s.push_back(QVector<double>());
        for(int j=0;j<row.size();j++)
        {
            s[i]<<row[j].toDouble();
        }
    }
}

void cXmlIO::readCsvVector(QXmlStreamReader &stream, QVector<double> &s)
{
    QString text = stream.readElementText();
    QStringList list = text.split(",", QString::SkipEmptyParts);
    s.clear();
    for(int i=0; i<list.size(); i++)
    {
        s.push_back(list.at(i).toDouble());
    }
}

void cXmlIO::write64BaseData(QXmlStreamWriter &stream, QString key, const QVector<QVector<double> > &s)
{
    stream.writeStartElement(key);

    QByteArray array;
    QDataStream dStream(&array,QIODevice::WriteOnly);
    dStream <<s;
    stream.writeCDATA(array.toBase64());
    stream.writeEndElement();

}
void cXmlIO::read64BaseData(QXmlStreamReader &stream, QVector<QVector<double> > &s)

{
    QByteArray array;
    QDataStream dStream(&array, QIODevice::ReadOnly);

    array.append(stream.readElementText());
    array = QByteArray::fromBase64(array);
    dStream>>s;

}

QTextStream& operator<<( QTextStream& str, const QVector<QVector<double> > &s)
{
    for(int i=0;i<s.size();i++)
    {
        for(int j=0;j<s[i].size();j++)
        {
            str<<(double)(s[i][j]);
            if(j<s[i].size()-1)
                str<<",";
        }
        str<<"\n";

    }
    return str;
}
