#include "SSEditor.h"
#include "Datei.h"
#include "DateiSystem.h"
#include "Bild.h"

// Inhalt der SSEditor Klasse aus SSEditor.h
// Konstruktor
SSEditor::SSEditor( char *pf )
{
    pfad = pf;
    pfad += "/live/shop";
    workPfad = "";
    fehler = "";
    ref = 1;
}

// Destruktor
SSEditor::~SSEditor()
{}

// nicht constant
bool SSEditor::prozessMessage( SKlient *zKlient )
{
    char message = 0;
    zKlient->getNachrichtEncrypted( &message, 1 );
    switch( message )
    {
    case 0x1: // Neue Datei erstellen
    {
        zKlient->sendeEncrypted( "\1", 1 );
        char typ = 0;
        zKlient->getNachrichtEncrypted( &typ, 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *name = new char[ len + 1 ];
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        name[ (int)len ] = 0;
        if( !len )
        {
            delete[] name;
            fehler = "Du musst einen Dateinamen angeben.";
            return 0;
        }
        Text n = name;
        delete[] name;
        if( n.hat( "/" ) || n.hat( "." ) )
        {
            fehler = "Du musst einen gültigen Dateinamen angeben.";
            return 0;
        }
        Text p = pfad.getText();
        p += workPfad.getText();
        p += "/";
        p += n;
        if( typ == 1 )
        {
            p += ".ltdb";
            if( !DateiPfadErstellen( p ) )
            {
                fehler = "Fehler beim erstellen der Datei.";
                return 0;
            }
            zKlient->sendeEncrypted( "\1", 1 );
            return 1;
        }
        if( typ == 2 )
        {
            p += ".ksgs";
            if( !DateiPfadErstellen( p ) )
            {
                fehler = "Fehler beim erstellen der Datei.";
                return 0;
            }
            zKlient->sendeEncrypted( "\1", 1 );
            return 1;
        }
        if( typ == 0 )
        {
            p += "/tmp";
            if( !DateiPfadErstellen( p ) )
            {
                fehler = "Fehler beim erstellen der Datei.";
                return 0;
            }
            DateiRemove( p );
            p.remove( p.getLength() - 4, p.getLength() );
            zKlient->sendeEncrypted( "\1", 1 );
            return 1;
        }
        fehler = "Ungültiger Dateityp.";
        return 0;
    }
    case 0x2: // Ordner open
    {
        zKlient->sendeEncrypted( "\1", 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *name = new char[ len + 1 ];
        name[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        if( Text( ".." ).istGleich( name ) )
        {
            if( workPfad.getLength() )
            {
                int anz = workPfad.anzahlVon( "/" );
                if( anz )
                    workPfad.remove( workPfad.positionVon( "/", anz - 1 ), workPfad.getLength() );
                else
                    workPfad = "";
            }
            delete[] name;
            zKlient->sendeEncrypted( "\1", 1 );
            return 1;
        }
        else
        {
            Text p = pfad.getText();
            p += workPfad.getText();
            p += "/";
            p += name;
            Datei d;
            d.setDatei( p );
            if( !d.existiert() )
            {
                delete[] name;
                fehler = "Die Datei konnte nicht gefunden werden.";
                return 0;
            }
            else
            {
                if( d.istOrdner() )
                {
                    workPfad += "/";
                    workPfad += name;
                }
                delete[] name;
                zKlient->sendeEncrypted( "\1", 1 );
                return 1;
            }
        }
    }
    case 0x3: // Bild laden
    {
        zKlient->sendeEncrypted( "\1", 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *dName = new char[ len + 1 ];
        dName[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( dName, len );
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *bName = new char[ len + 1 ];
        bName[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( bName, len );
        if( !textLength( dName ) || !textLength( bName ) )
        {
            delete[] dName;
            delete[] bName;
            fehler = "Du musst ein Bild und eine Datei angeben.";
            return 0;
        }
        Text p = pfad.getText();
        p += workPfad.getText();
        p += "/";
        p += dName;
        delete[] dName;
        if( !DateiExistiert( p ) )
        {
            delete[] bName;
            fehler = "Die Datei wurde nicht gefunden.";
            return 0;
        }
        LTDBDatei dat;
        dat.setDatei( p.getThis() );
        dat.leseDaten( 0 );
        Bild *b = dat.laden( 0, new Text( bName ) );
        delete[] bName;
        if( !b )
        {
            fehler = "Das Bild wurde nicht gefunden.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        int br = b->getBreite();
        int hi = b->getHeight();
        zKlient->sendeEncrypted( (char*)&br, 4 );
        zKlient->sendeEncrypted( (char*)&hi, 4 );
        char *buffer = (char*)b->getBuffer();
        __int64 gr = br * hi * 4;
        for( int i = 0, l = gr > 2048 ? 2048 : (int)gr; gr > 0; i += l, gr -= l, l = gr > 2048 ? 2048 : (int)gr )
            zKlient->sende( &( buffer[ i ] ), l );
        b->release();
        return 1;
    }
    case 0x4: // Datei remove
    {
        zKlient->sendeEncrypted( "\1", 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *name = new char[ len + 1 ];
        name[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        if( Text( name ).istGleich( ".." ) )
        {
            fehler = "Du kannst diese Datei nicht remove.";
            return 0;
        }
        Text p = pfad.getText();
        p += workPfad.getText();
        if( !Text( "." ).istGleich( name ) )
        {
            p += "/";
            p += name;
            int anz = workPfad.anzahlVon( "/" );
            if( anz )
                workPfad.remove( workPfad.positionVon( "/", anz - 1 ), workPfad.getLength() );
            else
                workPfad = "";
        }
        delete[] name;
        if( !DateiExistiert( p ) )
        {
            fehler = "Die Datei wurde nicht gefunden.";
            return 0;
        }
        if( !DateiRemove( p ) )
        {
            fehler = "Fehler beim remove der Datei.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        return 1;
    }
    case 0x5: // Text speichern
    {
        zKlient->sendeEncrypted( "\1", 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *name = new char[ len + 1 ];
        name[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        if( Text( name ).istGleich( ".." ) )
        {
            fehler = "Du kannst diese Datei nicht bearbeiten.";
            return 0;
        }
        Text p = pfad.getText();
        p += workPfad.getText();
        p += "/";
        p += name;
        delete[] name;
        if( !DateiExistiert( p ) )
        {
            fehler = "Die Datei wurde nicht gefunden.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        Datei d;
        d.setDatei( p );
        bool ok = d.open( Datei::Style::schreiben );
        char *buffer = new char[ 2048 ];
        int gr = 0;
        zKlient->getNachrichtEncrypted( (char*)&gr, 4 );
        while( gr > 0 )
        {
            int l = gr > 2048 ? 2048 : gr;
            zKlient->getNachricht( buffer, l );
            d.schreibe( buffer, l );
            gr -= l;
        }
        delete[] buffer;
        d.close();
        if( !ok )
        {
            fehler = "Es ist ein Fehler beim schreiben der Datei aufgetreten.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        return 1;
    }
    case 0x6: // Bild remove
    {
        zKlient->sendeEncrypted( "\1", 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *dName = new char[ len + 1 ];
        dName[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( dName, len );
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *bName = new char[ len + 1 ];
        bName[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( bName, len );
        if( !textLength( dName ) || !textLength( bName ) )
        {
            delete[] dName;
            delete[] bName;
            fehler = "Du musst ein Bild und eine Datei angeben.";
            return 0;
        }
        Text p = pfad.getText();
        p += workPfad.getText();
        p += "/";
        p += dName;
        delete[] dName;
        if( !DateiExistiert( p ) )
        {
            delete[] bName;
            fehler = "Die Datei wurde nicht gefunden.";
            return 0;
        }
        LTDBDatei dat;
        dat.setDatei( p.getThis() );
        dat.leseDaten( 0 );
        dat.remove( 0, new Text( bName ) );
        delete[] bName;
        zKlient->sendeEncrypted( "\1", 1 );
        return 1;
    }
    case 0x7: // Bild erstellen
    {
        zKlient->sendeEncrypted( "\1", 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *dName = new char[ len + 1 ];
        dName[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( dName, len );
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *bName = new char[ len + 1 ];
        bName[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( bName, len );
        if( !textLength( dName ) || !textLength( bName ) )
        {
            delete[] dName;
            delete[] bName;
            fehler = "Du musst ein Bild und eine Datei angeben.";
            return 0;
        }
        Text p = pfad.getText();
        p += workPfad.getText();
        p += "/";
        p += dName;
        delete[] dName;
        if( !DateiExistiert( p ) )
        {
            delete[] bName;
            fehler = "Die Datei wurde nicht gefunden.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        int br = 0;
        int hi = 0;
        zKlient->getNachrichtEncrypted( (char*)&br, 4 );
        zKlient->getNachrichtEncrypted( (char*)&hi, 4 );
        __int64 gr = br * hi * 4;
        Bild *b = new Bild();
        b->neuBild( br, hi, 0 );
        char *buffer = (char*)b->getBuffer();
        for( int i = 0, l = gr > 2048 ? 2048 : (int)gr; gr > 0; i += l, gr -= l, l = gr > 2048 ? 2048 : (int)gr )
            zKlient->getNachricht( &( buffer[ i ] ), l );
        LTDBDatei dat;
        dat.setDatei( p.getThis() );
        dat.leseDaten( 0 );
        dat.remove( 0, new Text( bName ) );
        if( dat.speichern( 0, b, new Text( bName ) ) < 0 )
        {
            delete[] bName;
            fehler = "Fehler beim speichern des Bildes.";
            return 0;
        }
        delete[] bName;
        zKlient->sendeEncrypted( "\1", 1 );
        return 1;
    }
    case 0x8: // Datei Liste herunterladen
    {
        Datei d;
        d.setDatei( Text( pfad.getText() ) += workPfad.getText() );
        RCArray< Text > *list = d.getDateiListe();
        if( !list )
        {
            fehler = "Es ist ein Fehler beim laden der Dateiliste aufgetreten.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        int anz = list->getEintragAnzahl();
        if( workPfad.getLength() )
            anz++;
        zKlient->sendeEncrypted( (char*)&anz, 4 );
        if( workPfad.getLength() )
        {
            zKlient->sendeEncrypted( "\2", 1 );
            zKlient->sendeEncrypted( "..", 2 );
            anz--;
        }
        for( int i = 0; i < anz; i++ )
        {
            char len = (char)list->z( i )->getLength();
            zKlient->sendeEncrypted( &len, 1 );
            zKlient->sendeEncrypted( list->z( i )->getText(), len );
        }
        list->release();
        return 1;
    }
    case 0x9: // Bild Liste herunterladen
    {
        zKlient->sendeEncrypted( "\1", 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *name = new char[ len + 1 ];
        name[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        if( !textLength( name ) )
        {
            delete[] name;
            fehler = "Du musst ein Bild und eine Datei angeben.";
            return 0;
        }
        Text p = pfad.getText();
        p += workPfad.getText();
        p += "/";
        p += name;
        delete[] name;
        if( !DateiExistiert( p ) )
        {
            fehler = "Die Datei wurde nicht gefunden.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        LTDBDatei dat;
        dat.setDatei( p.getThis() );
        dat.leseDaten( 0 );
        int anz = dat.getBildAnzahl();
        zKlient->sendeEncrypted( (char*)&anz, 4 );
        for( int i = 0; i < anz; i++ )
        {
            char len = (char)dat.zBildListe()->z( i )->getLength();
            zKlient->sendeEncrypted( &len, 1 );
            zKlient->sendeEncrypted( dat.zBildListe()->z( i )->getText(), len );
        }
        return 1;
    }
    case 0xA: // Text laden
    {
        zKlient->sendeEncrypted( "\1", 1 );
        unsigned char len = 0;
        zKlient->getNachrichtEncrypted( (char*)&len, 1 );
        char *name = new char[ len + 1 ];
        name[ (int)len ] = 0;
        if( len )
            zKlient->getNachrichtEncrypted( name, len );
        if( Text( name ).istGleich( ".." ) )
        {
            fehler = "Du kannst diese Datei nicht bearbeiten.";
            return 0;
        }
        Text p = pfad.getText();
        p += workPfad.getText();
        p += "/";
        p += name;
        delete[] name;
        if( !DateiExistiert( p ) )
        {
            fehler = "Die Datei wurde nicht gefunden.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        Datei d;
        d.setDatei( p );
        bool ok = d.open( Datei::Style::lesen );
        char *buffer = new char[ 2048 ];
        int gr = (int)d.getSize();
        zKlient->sendeEncrypted( (char*)&gr, 4 );
        while( gr > 0 )
        {
            int l = gr > 2048 ? 2048 : gr;
            d.lese( buffer, l );
            zKlient->sende( buffer, l );
            gr -= l;
        }
        delete[] buffer;
        d.close();
        if( !ok )
        {
            fehler = "Es ist ein Fehler beim schreiben der Datei aufgetreten.";
            return 0;
        }
        zKlient->sendeEncrypted( "\1", 1 );
        return 1;
    }
    default:
        fehler = "Unbekannte Nachricht. Eventuell ist der Client nicht auf dem neusten Stand.";
    }
    return 0;
}

// constant
char *SSEditor::getLetzterFehler() const
{
    return fehler;
}

// Reference Counting
SSEditor *SSEditor::getThis()
{
    ref++;
    return this;
}

SSEditor *SSEditor::release()
{
    ref--;
    if( !ref )
        delete this;
    return 0;
}