#ifndef LOADER_H
#define LOADER_H

#include <QDomDocument>
#include <QFile>
#include <QTextStream>
#include <QXmlSchema>
#include <QXmlSchemaValidator>
#include <QObject>
#include "adcore.h"

struct tbHeader
{
    int id;
    QString name;
};

struct tbAlien : tbHeader
{
    float speed;
    float health;
    float armor;
    float regeneration;
    bool isFlying;
    unsigned int score;
    int imgType;
    unsigned int prise;
};

struct tbSplash : tbHeader
{
    float speed;
    unsigned int lifetime;
    bool autoControl;
    bool keepOnAlien;
    int imgType;
    float animSpeed;
    float ZValue;
    QPainter::CompositionMode compositionMode;
};

struct tbTrigger : tbHeader
{
    float damage;
    float radius;
    int chance;
    bool delParent;
    srcTriggerType::aimType childAim;
    srcTriggerType::triggerType type;
    unsigned int timer;
    int count;
    float randomPosRadius;
};

struct tbTower : tbHeader
{
    float radius;
    unsigned int cost;
    unsigned int reload;
    unsigned int buildTime;
    float expByShot;
    float expByKill;
    float expByDamage;
    int splashId;
    int imgType;
};

struct tbChain
{
    int towerId;
    int parentSplashId;
    int childSplashId;
    int triggerId;
};

struct tbUpgrade
{
    int towerId;
    int triggerId;
    unsigned int cost;
    float towRadius;
    unsigned int towReload;
    float trigDamage;
    float trigDamageRadius;
};

struct tbMorph
{
    int fromId;
    int toId;
    int cost;
    float expRequired;
};

struct tbWavePart
{
    int alienId;
    unsigned int count;
//    int waveId;
};

struct tbWave
{
    int id;
    unsigned int timeout;
    unsigned int prise;
    //int type;
    QVector<tbWavePart> parts;
};

struct tbWaveOnLevel
{
    int levelId;
    int waveId;
};

struct tbMap : tbHeader
{
    unsigned int maxPlayers;
    QByteArray data;
    QSize size;
    int imgType;
};

struct tbTowerOnLevel
{
    tbTowerOnLevel() {levelId = -1; towerId = -1;}
    bool operator ==(const tbTowerOnLevel & other) const {return levelId == other.levelId && towerId == other.towerId;}
    int levelId;
    int towerId;
    //int enableWaveId;
};

struct tbLevel : tbHeader
{
    int mapId;
    unsigned int score;
    unsigned int money;
};

struct tbAnimation : tbHeader
{
    QStringList pathes;
};


class Loader : public QObject
{
public:
    Loader();
    void save(QString filename);
    void load(QString filename);
    Game_Data * loadlevel(int id);

    QHash <int,tbAlien> aliens;
    QHash <int,tbMap> maps;
    QHash <int,tbLevel> levels;
    QHash <int,tbSplash> splashes;
    QHash <int,tbTower> towers;
    QHash <int,tbTrigger> triggers;
    QHash <int,tbWave> waves;
    QHash <int,tbAnimation> animations;
    QMultiHash <int,tbWaveOnLevel> levWaves;
//    QMultiHash <int,tbWavePart> waveParts;
    QMultiHash <int,tbChain> chains;
    QMultiHash <int,tbMorph> morphs;
    QMultiHash <int,tbTowerOnLevel> levTowers;
    QMultiHash <int,tbUpgrade> upgrades;

private:
    QDomDocument * doc;
    QFile * file;

    void readAliens();
    void readMaps();
    void readLevels();
    void readMorphs();
    void readSplashes();
    void readTowers();
    void readLevTowers();
    void readTriggers();
    void readChains();
    void readWaves();
    void readLevWaves();
//    void readWaveParts();
    void readUpgrades();
    void readAnimations();

    void fillTowerChains(QList <int> * animIds, QList <tbChain> * chlist, QList <int> * trigIds, srcTowerType * stt, int parId, int parIndex, int * recursiveCheck);
    void validate(QString filename);
    QString createMapExample();
    void printMorphs(srcTowerType * stt, QString & str, const QString & prefix);
};

#endif // LOADER_H
