//Serializer.cpp

#include "stdio.h"
#include "Serial.h"

QString StartStr = "<?xml version = \"1.0\"?>\n<Scene>\n";
QString EndStr = "</Scene>";
QString StringStr1 = "<String Name = \"";
QString StringStr2 = "\"> ";
QString StringStr3 = " </String>\n";
QString BoolStr1 = "<Bool Name = \"";
QString BoolStr2 = "\"> ";
QString BoolStr3 = " </Bool>\n";
QString IntStr1 = "<Int Name = \"";
QString IntStr2 = "\"> ";
QString IntStr3 = " </Int>\n";
QString FloatStr1 = "<Float Name = \"";
QString FloatStr2 = "\"> ";
QString FloatStr3 = " </Float>\n";
QString VectorStr1 = "<Vector Name = \"";
QString VectorStr2 = "\"> ";
QString VectorStr3 = " </Vector>\n";
/// строка для записи ненужных символов
char TmpStr[256];

Serializer::Serializer()
{
    File = NULL;
    format = XML;
}

Serializer::~Serializer(){}

void Serializer::SerPic(int &Width, int &Height, char *Name)
{
    QString StrOpen = "<Screen>\n", StrClose = "</Screen>\n";
    int p = 0;
    if (!readWrite && !format) p = 1;

    if(readWrite)
    {
        //fprintf(f, StrOpen);
        File->write(StrOpen.toAscii());
        File->flush();
    }
    else
        //fread(TmpStr, 1, strlen(StrOpen), f);
        File->readLine(TmpStr, StrOpen.length() + p);

    SerStr(Name, "Attribute");

    SerInt(Width, "Width");
    SerInt(Height, "Height");


    if(readWrite)
    {
        //fprintf(f, StrClose);
        File->write(StrClose.toAscii());
        File->flush();
    }
    else
        //fread(TmpStr, 1, strlen(StrClose), f);
        File->readLine(TmpStr, StrClose.length() + p);
}

void Serializer::SerCam(Vector3D &Camera, char *Name)
{
    int p = 0;
    if (!readWrite && !format) p = 1;

    QString StrOpen = "<Camera>\n", StrClose = "</Camera>\n";
    if(readWrite)
    {
        //fprintf(f, StrOpen);
        File->write(StrOpen.toAscii());
        File->flush();
    }
    else
        //fread(TmpStr, 1, strlen(StrOpen), f);
        File->readLine(TmpStr, StrOpen.length() + p);

    SerStr(Name, "Attribute");

    SerVec(Camera, "Position");

    if(readWrite)
    {
        //fprintf(f, StrClose);
        File->write(StrClose.toAscii());
        File->flush();
    }
    else
        //fread(TmpStr, 1, strlen(StrClose), f);
        File->readLine(TmpStr, StrClose.length() + p);
}

void Serializer::SerMat(Mater &Material, char * Name)
{
    int p = 0;
    if (!readWrite && !format) p = 1;

    QString StrOpen = "<Material>\n", StrClose = "</Material>\n";
    if(readWrite)
    {
        //fprintf(f, StrOpen);
        File->write(StrOpen.toAscii());
        File->flush();
    }
    else
        //fread(TmpStr, 1, strlen(StrOpen), f);
        File->readLine(TmpStr, StrOpen.length() + p);

    SerStr (Name, "Attribute");

    SerVec(Material.Colour, "Color");
    SerVec(Material.Specular, "Specular");
    SerVec(Material.Reflectivity, "Reflectivity");

    if(readWrite)
    {
        //fprintf(f, StrClose);
        File->write(StrClose.toAscii());
        File->flush();
    }
    else
        //fread(TmpStr, 1, strlen(StrClose), f);
        File->readLine(TmpStr, StrClose.length() + p);
}

void Serializer::SerSph(Sphere &Sphere, char *Name)
{
    int p = 0;
    if (!readWrite && !format) p = 1;

    QString StrOpen = "<Sphere>\n", StrClose = "</Sphere>\n";
    if(readWrite)
    {
        //fprintf(f, StrOpen);
        File->write(StrOpen.toAscii());
        File->flush();
    }
    else
        //fread(TmpStr, 1, strlen(StrOpen), f);
        File->readLine(TmpStr, StrOpen.length() + p);

    SerStr(Name, "Attribute");
	
    SerVec(Sphere.Position, "Position");
    SerFloat(Sphere.Radius, "Radius");
    SerMat(Sphere.Material, "Material");

    if(readWrite)
    {
        //fprintf(f, StrClose);
        File->write(StrClose.toAscii());
        File->flush();
    }
    else
        //fread(TmpStr, 1, strlen(StrClose), f);
        File->readLine(TmpStr, StrClose.length() + p);
}

void Serializer::SerThor(Thor &Thor, char *Name)
{
    int p = 0;
    if (!readWrite && !format) p = 1;

    QString StrOpen = "<Thor>\n", StrClose = "</Thor>\n";
    if(readWrite)
    {
        //fprintf(f, StrOpen);
        File->write(StrOpen.toAscii());
        File->flush();
    }
    else
        //fread(TmpStr, 1, strlen(StrOpen), f);
        File->readLine(TmpStr, StrOpen.length() + p);

    SerStr(Name, "Attribute");

    SerVec(Thor.PosCen, "Position");
    SerFloat(Thor.Radius, "Radius");
    SerFloat(Thor.Width, "Width");
    SerMat(Thor.Material, "Material");

    if(readWrite)
    {
        //fprintf(f, StrClose);
        File->write(StrClose.toAscii());
        File->flush();
    }
    else
        //fread(TmpStr, 1, strlen(StrClose), f);
        File->readLine(TmpStr, StrClose.length() + p);
}

void Serializer::SerLight(Light &Light, char *Name)
{
    int p = 0;
    if (!readWrite && !format) p = 1;

    QString StrOpen = "<Light>\n", StrClose = "</Light>\n";
    if(readWrite)
    {
        //fprintf(f, StrOpen);
        File->write(StrOpen.toAscii());
        File->flush();
    }
    else
        //fread(TmpStr, 1, strlen(StrOpen), f);
        File->readLine(TmpStr, StrOpen.length() + p);

    SerStr(Name, "Caption");
	
    SerVec(Light.Position, "Position");
    SerVec(Light.Colour, "Color");
    SerFloat(Light.ConstAttenuation, "ConstAttenuation");
    SerFloat(Light.LinearAttenuation, "LinearAttenuation");
    SerFloat(Light.QuadricAttenuation, "QuadricAttenuation");

    if(readWrite)
    {
        //fprintf(f, StrClose);
        File->write(StrClose.toAscii());
        File->flush();
    }
    else
        //fread(TmpStr, 1, strlen(StrClose), f);
        File->readLine(TmpStr, StrClose.length() + p);
}

XMLS::XMLS()
{
    format = XML;
    readWrite = WR;
}

XMLS::~XMLS()
{
}

bool XMLS::Start(QString FileName)
{

    File = new QFile(FileName);
    if(!File->open(QIODevice::WriteOnly))
        return false;

    //int Len = StartStr.length();
	
    File->write(StartStr.toAscii());
    File->flush();

    return true;
}

void XMLS::SerStr(char * Value, char * Name)
{       
    //fprintf(f, StringStr, Name, Value);
    File->write(StringStr1.toAscii());
    File->write(Name);
    File->write(StringStr2.toAscii());
    File->write(Value);
    File->write(StringStr3.toAscii());
    File->flush();
}

void XMLS::SerBool(bool &Value, char * Name)
{
    //fprintf(f, '\t');
    File->write(BoolStr1.toAscii());
    File->write(Name);
    File->write(BoolStr2.toAscii());
    if(Value)
    {
        //fprintf(f, BoolStr, Name, "true");
        File->write("true");
    }
    else
        //fprintf(f, BoolStr, Name, "false");
        File->write("false");

    File->write(BoolStr3.toAscii());
    File->flush();
}

void XMLS::SerInt(int &Value, char * Name)
{
    //fprintf(f, '\t');
    //fprintf(f, IntStr, Name, Value);
    File->write(IntStr1.toAscii());
    File->write(Name);
    File->write(IntStr2.toAscii());
    char buffer[20];
    char *p;
    p = itoa(Value, buffer, 10);
    File->write(p);;
    File->write(IntStr3.toAscii());
    File->flush();
}

void XMLS::SerFloat(float &Value, char * Name)
{
    //fprintf(f, '\t');
    //fprintf(f, FloatStr, Name, Value);
    File->write(FloatStr1.toAscii());
    File->write(Name);
    File->write(FloatStr2.toAscii());
    char buffer[20];
    sprintf(buffer, "%f", Value );
    File->write(buffer);
    File->write(FloatStr3.toAscii());
    File->flush();
}

void XMLS::SerVec(Vector3D &Value, char * Name)
{
    //fprintf(f, '\t');
    //fprintf(f, VectorStr, Name, Value.X, Value.Y, Value.Z);
    File->write(VectorStr1.toAscii());
    File->write(Name);
    File->write(VectorStr2.toAscii());
    char buffer[20];
    sprintf(buffer, "%f %f %f", Value.X, Value.Y, Value.Z);
    File->write(buffer);
    File->write(VectorStr3.toAscii());
    File->flush();
}

void XMLS::End()
{
    //int Len = strlen(EndStr);
    //fwrite(EndStr, 1, Len, f);
    File->write(EndStr.toAscii());
    File->flush();
    File->close();
    delete File;
}

XMLL::XMLL()
{
    format = XML;
    readWrite = RE;
}

XMLL::~XMLL()
{
}

bool XMLL::Start(QString FileName)
{
    //fscanf(f, StartStr);

    File = new QFile(FileName);
    if(!File->open(QIODevice::ReadOnly))
        return false;

    char *temp = new char [256];
    File->read(temp, StartStr.length());
    delete temp;

    return true;
}

void XMLL::SerStr(char * Value, char * Name)
{
    int i;
    char c, p;

    for(i = 0; i < 2; i++)
    {
        do
        {
            File->getChar(&c);
            //c = fgetc(f);
            if(c == EOF) return;
        }
        while(c != '\"');
    }

    do
    {
        File->getChar(&c);
        //c = fgetc(f);
        if(c == EOF) return;
    }
    while(c != '>');
    File->getChar(&p);
    //fgetc(f);

    i = 0;

    do
    {

        File->getChar(&c);
        //c = fgetc(f);
        if(c == EOF) return;

        TmpStr[i] = c;
        i++;
    }
    while(c != '<');
    TmpStr[i-2] = 0;

    //fread(TmpStr, 1, strlen("/Int>\n"), f);
    File->read(TmpStr, strlen("/Int>\n"));
}

void XMLL::SerBool(bool &Value, char * Name)
{
    int i;
    char c;
    char str[256];

    for(i = 0; i < 2; i++)
    {
        do
        {
            //c = fgetc(f);
            File->getChar(&c);
            if(c == EOF) return;
        }
    while(c != '\"');
    }

    do
    {
        //c = fgetc(f);
        File->getChar(&c);
        if(c == EOF) return;
    }
    while(c != '>');
    //fgetc(f);
    File->getChar(&c);

    //fscanf(f, "%s", str);
    File->readLine(str, sizeof(str));
    if(!strcmp(str, "true"))
        Value = true;
    else
        Value = false;
    //fread(TmpStr, 1, strlen("</Bool>\n"), f);
    File->read(TmpStr, strlen("</Bool>\n"));
}

void XMLL::SerInt(int &Value, char * Name)
{
    int i;
    char c;
    char str[256];

    for(i = 0; i < 2; i++)
    {
        do
        {
            //c = fgetc(f);
            File->getChar(&c);
            if(c == EOF) return;
        }
    while(c != '\"');
    }

    do
    {
        //c = fgetc(f);
        File->getChar(&c);
        if(c == EOF) return;
    }
    while(c != '>');
    //fgetc(f);
    File->getChar(&c);

    File->readLine(str, sizeof(str));
    sscanf(str, "%d", &Value);
    //fread(TmpStr, 1, strlen("</Int>\n"), f);
    File->read(TmpStr, strlen("</Int>\\n"));
}

void XMLL::SerFloat(float &Value, char * Name)
{
    int i;
    char c;
    char str[256];

    for(i = 0; i < 2; i++)
    {
        do
        {
            //c = fgetc(f);
            File->getChar(&c);
            if(c == EOF) return;
        }
    while(c != '\"');
    }

    do
    {
        //c = fgetc(f);
        File->getChar(&c);
        if(c == EOF) return;
    }
    while(c != '>');
    //fgetc(f);
    File->getChar(&c);

    File->readLine(str, sizeof(str));
    sscanf(str, "%f", &Value);
    //fscanf(f, "%f", &Value);
    //fread(TmpStr, 1, strlen("</Float>\n"), f);
    File->read(TmpStr, strlen("</Float>\n"));
}

void XMLL::SerVec(Vector3D &Value, char * Name)
{
    int i;
    char c;
    char str[256];

    for(i = 0; i < 2; i++)
    {
        do
        {
            //c = fgetc(f);
            File->getChar(&c);
            if(c == EOF) return;
        }
    while(c != '\"');
    }

    do
    {
        //c = fgetc(f);
        File->getChar(&c);
        if(c == EOF) return;
    }
    while(c != '>');
    //fgetc(f);
    File->getChar(&c);

    File->readLine(str, sizeof(str));
    //sscanf(str, "%d", &Value);
    sscanf(str, "%f %f %f", &Value.X, &Value.Y, &Value.Z);
    //fread(TmpStr, 1, strlen("</Float>\n"), f);
    File->read(TmpStr, strlen("</Float>\n"));
}

void XMLL::End()
{
    //int Len = strlen(EndStr);
    //fread(TmpStr, 1, Len, f);
    File->read(TmpStr, EndStr.length());
    File->close();
    delete File;
}

BinS::BinS()
{
    format = Bin;
    readWrite = WR;
}

BinS::~BinS()
{
}

bool BinS::Start(QString FileName)
{
    //f = fopen(FileName, "wb");
    //return (f != NULL);

    File = new QFile(FileName);
    return (File->open(QIODevice::WriteOnly));
}

void BinS::SerStr(char * Value, char * Name)
{
    //int Len = strlen(Value);
    //fwrite(&Len, sizeof(int), 1, f);
    //fwrite(Value, 1, Len, f); 
    File->write("char* ");
    File->write(Value, sizeof(Value));
    File->write("\n", 1);
    File->flush();
}

void BinS::SerBool(bool &Value, char * Name)
{
    //fwrite(&Value, sizeof(bool), 1, f);
    File->write("bool ");
    char buffer[20];
    sprintf(buffer, "%b", Value);
    File->write(buffer);
    File->write("\n", 1);
    File->flush();
}

void BinS::SerInt(int &Value, char * Name)
{
    //fwrite(&Value, sizeof(int), 1, f);
    File->write("int ");
    char buffer[20];
    sprintf(buffer, "%i", Value);
    File->write(buffer);
    File->write("\n", 1);
    File->flush();
}

void BinS::SerFloat(float &Value, char * Name)
{
    //fwrite(&Value, sizeof(float), 1, f);
    File->write("float ");
    char buffer[20];
    sprintf(buffer, "%f", Value);
    File->write(buffer);
    File->write("\n", 1);
    File->flush();
}

void BinS::SerVec(Vector3D &Value, char * Name)
{
    SerStr(Name, "Vector3D");
    SerFloat(Value.X);
    SerFloat(Value.Y);
    SerFloat(Value.Z);
}

void BinS::End()
{
    File->close();
    delete File;
}

BinL::BinL()
{
    format = Bin;
    readWrite = RE;
}

BinL::~BinL()
{
}

bool BinL::Start(QString FileName)
{
    //f = fopen(FileName, "rb");
    //return (f != NULL);
    File = new QFile(FileName);
    if(!File->open(QIODevice::ReadOnly))
        return false;

    char buffer[256];
    //File->readLine(buffer, sizeof(buffer));
    return true;
}

void BinL::SerStr(char * Value, char * Name)
{
    //int Len;
    //fread(&Len, sizeof(int), 1, f);
    //fread(TmpStr, 1, Len, f);
    char buffer[256];
    File->readLine(buffer, sizeof(buffer));
    char buf1 = 'A';
}

void BinL::SerBool(bool &Value, char * Name)
{
    //fread(&Value, sizeof(bool), 1, f);
    char buffer[256];
    char buf[8];
    File->readLine(buffer, qint64(sizeof(buffer)));
    sscanf(buffer, "%s %b", buf, &Value);
    //delete [] buf;
    //delete [] buffer;
    char buf1 = 'A';
}

void BinL::SerInt(int &Value, char * Name)
{
    //fread(&Value, sizeof(int), 1, f);
    char buffer[256];
    char buf[8];
    File->readLine(buffer, qint64(sizeof(buffer)));
    sscanf(buffer, "%s %d", buf, &Value);
    //delete [] buf;
    //delete [] buffer;
    char buf1 = 'A';
}

void BinL::SerFloat(float &Value, char * Name)
{
    //fread(&Value, sizeof(float), 1, f);
    char buffer[256];
    char buf[8];
    File->readLine(buffer, qint64(sizeof(buffer)));
    sscanf(buffer, "%s %f", buf, &Value);
    //delete [] buf;
    //delete [] buffer;
    char buf1 = 'A';
}

void BinL::SerVec(Vector3D &Value, char * Name)
{
    SerStr(Name, "Caption");
    SerFloat(Value.X);
    SerFloat(Value.Y);
    SerFloat(Value.Z);
    char buf1 = 'A';
}

void BinL::End()
{
    delete File;
}
