#include "jeu.h"

int jeuMulti( SDL_Surface* screen, Config settings )
{
    /// [1] Pr�paration des composants
    // [1.1] Composants de base SDL
    SDL_Event event;
    bool done = false;
    Uint32 tempsPrecedent(0), ecart(0), frameRate(1000/12), dernierStart(0);//12fps

    // [1.2] Gestionnaires
    Collisions collisionneur(screen, settings.xSize, settings.ySize);
    TableauPower powerCreater(screen, &collisionneur, settings.nbPouvoirs );
    Score tabScore;
    clearScore( &tabScore );

    // [1.3] Gestion param�tres
    int nbJoueurs = settings.nbJoueurs;
    if (nbJoueurs < 1)
        return 1;
    else if (nbJoueurs > 12)
        return 1;

    // [1.4] Cr�ation des images des liners
    if (!initialisationPict())
        return false;

    // [1.5] Cr�ation du texm_xl.tRender
    TextRender texter( "Polices/", nbJoueurs, settings.ySize );
    texter.preLoadName( settings.pseudo[0], ROUGE );
    texter.preLoadName( settings.pseudo[1], BLEU );
    texter.preLoadName( settings.pseudo[2], VERT );
    texter.preLoadName( settings.pseudo[3], JAUNE );
    texter.preLoadName( settings.pseudo[4], ROSE );
    texter.preLoadName( settings.pseudo[5], CYAN );
    texter.preLoadName( settings.pseudo[6], ORANGE );
    texter.preLoadName( settings.pseudo[7], VIOLET );
    texter.preLoadName( settings.pseudo[8], GRIS );
    texter.preLoadName( settings.pseudo[9], MARINE );
    texter.preLoadName( settings.pseudo[10], PLUME );
    texter.preLoadName( settings.pseudo[11], MARRON );

    // [1.6] Cr�ation des liners
    int nbVivants(0), nbVivantsPrec(4);
    int guidon[12], nbPoints[nbJoueurs];
    Liner* hyperliner[nbJoueurs];
    for (int i(0); i<nbJoueurs; i++){
        hyperliner[i] = new Liner(5, 5, DROITE, i, screen, texter.takeName(settings.pseudo[i]), &collisionneur, &powerCreater) ;
        guidon[i] = nbPoints[i] = 0;
    }

    // [1.7] Cr�ation du d�marreur
    Starter myStarter( settings.xSize, settings.ySize );
    myStarter.loadAreas();

    /// [2] Boucle principale
    while (!done)
    {
        // [2.1] Gestion �v�nements
        while (SDL_PollEvent(&event))
        {
            switch (event.type)
            {
            case SDL_QUIT:
                done = true;
                break;
            case SDL_KEYDOWN:
                // Controles de joueurs
                for ( int i(0); i < nbJoueurs; i ++ )
                {
                    if ( event.key.keysym.sym == settings.cmd[i][0] )
                        guidon[i] = TOURNE_GAUCHE ;
                    else if ( event.key.keysym.sym == settings.cmd[i][2] )
                        guidon[i] = TOURNE_DROITE ;

                    if ( event.key.keysym.sym == settings.cmd[i][1] && nbVivants > 1 )
                        hyperliner[i]->utiliserPouvoir();
                }

                // Commandes classiques
                switch (event.key.keysym.sym)
                {
                case SDLK_ESCAPE:
                    done = true;
                    break;
                case SDLK_p:
                case SDLK_KP_ENTER:
                case SDLK_RETURN:
                    // Pause
                    dernierStart = SDL_GetTicks();

                    // R�initialisation
                    nbVivants = nbJoueurs;
                    collisionneur.reinitialiser();
                    powerCreater.initialiser();

                    // Placement
                    myStarter.spawnLiners( hyperliner, nbJoueurs );

                    break;
                /*case SDLK_RIGHT:
                    guidon[0] = TOURNE_DROITE;
                    break;
                case SDLK_LEFT:
                    guidon[0] = TOURNE_GAUCHE;
                    break;
                case SDLK_UP:
                case SDLK_DOWN:
                    if ( hyperliner[0] != 0 && nbVivants > 1 )
                        hyperliner[0]->utiliserPouvoir();
                    break;
                case SDLK_d:
                    guidon[1] = TOURNE_DROITE;
                    break;
                case SDLK_q:
                case SDLK_a:
                    guidon[1] = TOURNE_GAUCHE;
                    break;
                case SDLK_s:
                case SDLK_z:
                case SDLK_w:
                    if ( nbJoueurs > 1 && hyperliner[1] != 0 && nbVivants > 1 )
                        hyperliner[1]->utiliserPouvoir();
                    break;
                case SDLK_l:
                    guidon[2] = TOURNE_DROITE;
                    break;
                case SDLK_j:
                    guidon[2] = TOURNE_GAUCHE;
                    break;
                case SDLK_k:
                case SDLK_i:
                    if ( nbJoueurs > 2 && hyperliner[2] != 0 && nbVivants > 1 )
                        hyperliner[2]->utiliserPouvoir();
                    break;
                case SDLK_KP6:
                    guidon[3] = TOURNE_DROITE;
                    break;
                case SDLK_KP4:
                    guidon[3] = TOURNE_GAUCHE;
                    break;
                case SDLK_KP5:
                case SDLK_KP8:
                    if ( nbJoueurs > 3 && hyperliner[3] != 0 && nbVivants > 1 )
                        hyperliner[3]->utiliserPouvoir();
                    break;*/
                default:
                    break;
                }
            } // end switch event type
        } // end of message processing

        // [2.2] Calculs
            // On compte les survivants
            nbVivantsPrec = nbVivants;
            nbVivants = 0;

            for (int i(0); i<nbJoueurs; i++)
                if (hyperliner[i] != 0)
                    if (hyperliner[i]->estVivant())
                        nbVivants++;

            if ( nbVivants != nbVivantsPrec && nbVivants < 2 )
                updateScore( &tabScore, hyperliner, nbJoueurs );

            if ( nbVivants != nbVivantsPrec && nbJoueurs > 1 )
                powerCreater.bruiterMort();

            nbVivants = (nbJoueurs == 1)? 2 : nbVivants;/**< DEBUG : � enlever */

            // Si il y en a assez, la partie continue
            if (nbVivants > 1)
                for (int i(0); i<nbJoueurs; i++){
                    if (hyperliner[i] != 0 && SDL_GetTicks() - dernierStart > 3000)
                    {
                        hyperliner[i]->actualiser(guidon[i]);
                        hyperliner[i]->direEstFini( false );
                    }
                    else if (hyperliner[i] != 0)
                        hyperliner[i]->direEstFini( true );
                    guidon[i] = 0;
                }
            else
            {
                for (int i(0); i<nbJoueurs; i++)
                    if (hyperliner[i] != 0)
                        hyperliner[i]->direEstFini( true );
            }

            // On g�re les collisions en m�me temps pour plus d'�quit�
            for (int i(0); i<nbJoueurs; i++){
                if (hyperliner[i] != 0)
                {
                    hyperliner[i]->collisioner();
                }
            }

            // On nettoie les pouvoirs utilis�s
            powerCreater.actualiser();

        // [2.3] Dessin des composants
            SDL_FillRect(screen, 0, 0);

            collisionneur.afficher();
            powerCreater.afficher();
            for (int i(0); i<nbJoueurs; i++)
            {
                if (hyperliner[i] != 0)
                    hyperliner[i]->afficher();
            }

            if ( nbVivants < 2 ) { // Jeu en fini
                    displayScore( &tabScore, &texter, nbJoueurs, screen, settings.pseudo );
                    SDL_ShowCursor( SDL_ENABLE );
            }
            else SDL_ShowCursor( SDL_DISABLE ); // Jeu en cours

            SDL_Flip(screen);

        // [2.4] Gestion du temps
            /*ecart = SDL_GetTicks() - tempsPrecedent;
            if (ecart < frameRate)
                SDL_Delay(frameRate - ecart);
            tempsPrecedent = SDL_GetTicks();*/
            ecart = SDL_GetTicks() - tempsPrecedent;
            while (ecart < frameRate)
            {
                if ( frameRate - ecart > 4 )
                    SDL_Delay( frameRate - ecart - 4 );
                ecart = SDL_GetTicks() - tempsPrecedent;
            }
            tempsPrecedent = SDL_GetTicks();

    } //fin bcl principale

    /// [3] Etape de fin
    // Destruction des composants dynamiques
    for (int i(0); i<nbJoueurs; i++)
        if (hyperliner[i] != 0)
                delete hyperliner[i];
    fermeturePict();

    return 0;
}

Config readConfig()
{
    /// Config
    Config settings;
    std::string const source("config.txt");
    std::ifstream fluxIn(source.c_str());
    short optEcran;

    /// Attributions
    if (fluxIn)
    {
        //Ouverture fichier succ�s
        fluxIn >> settings.xSize;
        fluxIn >> settings.ySize;
        fluxIn >> settings.nbJoueurs;
        fluxIn >> optEcran;
        fluxIn >> settings.nbPouvoirs;

        for (int i(0); i<12; i++)
        {
            fluxIn >> settings.pseudo[i];
            fluxIn >> settings.cmd[i][0];
            fluxIn >> settings.cmd[i][1];
            fluxIn >> settings.cmd[i][2];
        }
    }
    else
    {
        //Echec ouverture fichier
        std::cout << "ERREUR: impossible de lire le fichier " << source << " ." << std::endl;

        //Param�tres par d�faut
        settings.xSize = 45;
        settings.ySize = 30;
        settings.nbJoueurs = 2;
        optEcran = 0;
        settings.nbPouvoirs = 5;

        for (int i(0); i<4; i++)
            settings.pseudo[i] = "Joueur " + intToStr(i);
    }

    /// Optimisation
    if ( optEcran != 2 ) {
        settings.pleinEcran = optEcran;
    }
    else {
        settings.pleinEcran = true;
        const SDL_VideoInfo* fenetreInfo = SDL_GetVideoInfo();
        settings.xSize = fenetreInfo->current_w / 20;
        settings.ySize = fenetreInfo->current_h / 20;
    }

    /// Fin
    return settings;
}

void updateScore( Score* tabScore, Liner** hyperliner, int nbJoueurs )
{
    if ( hyperliner[0] == 0x0 ) return; // S�curit�

    /// Compter les scores
    int murder;
    for ( Uint16 i(0); i < nbJoueurs; i++) {
        murder = hyperliner[i]->getMeurtrier();
        if ( murder != -1 ) tabScore->mort[i]++; // Morts
        if ( murder != -1 && murder != 5 ) tabScore->frag[murder]++; // Frags
    }
}

void displayScore( Score* tabScore, TextRender* texter, int nbJoueurs, SDL_Surface* screen, std::string pseudo[12] )
{
    SDL_Rect pos = { 50, 50, 0, 0 }, blanc;
    const int espace( (screen->h - 100 ) / nbJoueurs );
    std::string chaine;
    SDL_Surface* bande;
    for ( Uint16 i(0); i < nbJoueurs; i++ ) {
        /// Texte
        chaine = pseudo[i] + " [" + intToStr(i+1) + "] : " + intToStr(tabScore->frag[i]) + " frags; " + intToStr(tabScore->mort[i]) + " morts.";

        /// Text rendering
        bande = texter->tRendLite( i, chaine );

        /// Blanco
        blanc.x = pos.x - 4;
        blanc.y = pos.y - 2;
        blanc.h = bande->h + 4;
        blanc.w = bande->w + 8;
        SDL_FillRect( screen, &blanc, 0xffffff );

        /// Application bande
        SDL_BlitSurface( texter->takeLite(i), 0, screen, &pos );
        pos.y += espace;
    }
}

void clearScore ( Score* tabScore )
{
    for ( Uint16 i(0); i < 12; i++) {
        tabScore->mort[i] = tabScore->frag[i] = 0; // Initialisaton
    }
}