#pragma once

#include "EditorKlient.h"
#include <Punkt.h>
#include <Critical.h>
#include <functional>
#include <Welt2D.h>
#include <Model2D.h>
#include <GSLDateiV.h>

namespace Editor
{
    struct ResourceDaten
    {
        int id;
        Text path;
    };

    struct SpielerDaten //: public Model
    {
        int id;
        Punkt pos;
        double rot;
        double beschleunigung;
        int maxStabilit�t;
        int maxEnergie;
        double reparatur;
        double akkuLeistung;
        int laserIntensit�t;
        int laserEffizienz;
        int laserTempo;
        double wendigkeit;
        double antriebEffizienz;
        double energieSchild;
        double energieSchildEffizienz;
        int netzwerk;
        int skillPunkte;
        int m2d;
        int bild;

        SpielerDaten();
        SpielerDaten( const SpielerDaten &daten );
    };

    struct TeamDaten// : public Model
    {
        int id;
        int maxPunkte;
        double beschleunigung;
        int maxStabilit�t;
        int maxEnergie;
        double reparatur;
        double akkuLeistung;
        int laserIntensit�t;
        int laserEffizienz;
        int laserTempo;
        double wendigkeit;
        double antriebEffizienz;
        double energieSchild;
        double energieSchildEffizienz;
        int punkte;

        TeamDaten();
        TeamDaten( const TeamDaten &daten );
    };

    struct ObjektDaten //: public Model
    {
        Punkt pos;
        float rot;
        float scale;
        int id;
        int m2d;
        int bild;
        int style;
        int maxStabilit�t;
        int maxEnergie;
        int energieRadius;
        double reparatur;
        double akkuLeistung;
        char team;

        ObjektDaten();
        ObjektDaten( const ObjektDaten &daten );
    };

    class EditorObject : public Model2DObject
    {
    public:
        enum ObjektTyp
        {
            SPIELER,
            OBJEKT
        };

    private:
        ObjektTyp typ;
        int id;

    public:
        EditorObject( ObjektTyp typ, int id );
        virtual ~EditorObject();
        virtual void update() = 0;
        bool isObjekt( ObjektTyp typ, int id );
    };

    class EdSpieler : public EditorObject
    {
    private:
        SpielerDaten *mdl;

    public:
        EdSpieler( SpielerDaten *model );
        ~EdSpieler();
        void update();
    };

    class EdObjekt : public EditorObject
    {
    private:
        ObjektDaten *mdl;

    public:
        EdObjekt( ObjektDaten *model );
        ~EdObjekt();
        void update();
    };

    class UpdateObserver //: public View
    {
    private:
        std::function< void() > f;

    public:
        UpdateObserver( std::function< void() > f );
        //void update( Model *m ) override;
    };

    typedef GSL::GSLDateiV *( *GetGSLDatei )( );

    class KarteDaten : public Thread
    {
    private:
        EditorKlient *client;
        SpielerTeamStruktur *sts;
        Array< SpielerDaten * > spieler;
        Array< TeamDaten * > teams;
        Array< ObjektDaten * > objekte;
        Array< ResourceDaten * > resources;
        Text error;
        Array< std::function< void() > > aktionen;
        Critical cs;
        Welt2D *welt;
       // RCArray< View > views;
        Punkt size;
        GetGSLDatei getGSLDatei;
        bool exit;

        void loadSpielResourcePathsFromFolder( const char *folderPath, RCArray< Text > *zPaths );

    public:
        KarteDaten( EditorKlient *client, SpielerTeamStruktur *sts );
        ~KarteDaten();
        void addObjekt( ObjektDaten &daten, std::function< void( int ) > callBack );
        void removeObjekt( int index );
        void thread() override;
        ResourceDaten *getResource( int index );
        ObjektDaten *getObjekt( int index );
        SpielerDaten *getSpieler( int index );
        TeamDaten *getTeam( int index );
        const char *getTeamName( int index );
        int getSpielerIndexById( int id );
        int getSpielerAnzahl() const;
        int getTeamIndexById( int id );
        int getTeamAnzahl() const;
        int getObjektIndexById( int id );
        int getObjektAnzahl() const;
        int getResourceIndexById( int id );
        int getResourceAnzahl();
        bool hasError() const;
        char *getError() const;
        bool hasAktions() const;
        Welt2D *getWelt() const;
        Welt2D *zWelt() const;
        void getResourceIdFromPath( const char *path, std::function< void( int ) > callBack );
        bool doesResourceExist( const char *path );
        Model2DData *loadModelFromRessource( int id );
        Bild *loadBildFromRessource( int id );
        Model2DData *loadModelFromPath( const char *path );
        Bild *loadBildFromPath( const char *path );
        void loadUnusedResourcePaths( std::function< void( RCArray< Text > * ) > callBack );
        // l�scht das objekt wenn es nicht mehr gebraucht wird und beendet den Thread
        Thread *release() override;
    };
}