//  Copyright (2013) Cédric Coussinet (cedric.coussinet@nomoseed.net)
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published
//  by the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program. If not, see <http://www.gnu.org/licenses/>

#include "benchmark.h"
#include "worldsquare.h"
#include <stdlib.h>
#include <string.h>

static char map[256];

static nomoLogFlag* logFlags;

static sensors agent;

void benchmarkInputs (){
    short shift;
    short i;
    for(i=0;i<getAgentNumberActiveWorldSquareXML();i++)
    {
        agent = getAgentSensorsWorldSquareXML(i);
        shift = i * 7; // 7 correspondant au nombre d'entrées par agent.
        nomoInput(INPUT_HUE_WORLDSQUARE_ID + shift, agent.hue);
        nomoInput(INPUT_BUMPER_WORLDSQUARE_ID + shift, agent.bumper);
        nomoInput(INPUT_SONAR_WORLDSQUARE_ID + shift, agent.sonar);
        nomoInput(INPUT_SPHERES_NUMBER_WORLDSQUARE_ID + shift, agent.sphere);
        if (agent.strength[0] == 1.0)
            nomoInput(INPUT_STRENGTH_WORLDSQUARE_ID + shift, agent.strength);
        if (agent.sound[0] != -1.0)
            nomoInput(INPUT_SOUND_WORLDSQUARE_ID + shift, agent.sound);
        nomoInput(INPUT_RANDOM_WORLDSQUARE_ID + shift, agent.random);
    }
}

void benchmarkUpdateMap (){
    readWorldSquareXML (map);
}

void benchmarkSaveMap (){
    saveWorldSquareXML (map);
}

void benchmarkTriggers (){
    assumeWorldSquareXML ();
    updateInputsWorldSquareXML ();
    benchmarkInputs ();
    nomoTriggers ();
}

void benchmarkTriggersWithLog (const nomoLogFlag logFlag, const nomoLogPositionFlag logPositionFlag, const nomoFileFlag fileFlag){
    if (logFlag != logFlags[0]){
        int i;
        for (i=0;i<1000;i++)
            logFlags[i] = logFlag;
    }
    assumeWorldSquareXML ();
    updateInputsWorldSquareXML ();
    benchmarkInputs ();
    nomoTriggersWithLog (logFlags, logPositionFlag, fileFlag);
}

void benchmarkTriggersWithSave (){
    assumeWorldSquareXML ();
    saveWorldSquareXML (map);
    updateInputsWorldSquareXML ();
    benchmarkInputs ();
    nomoTriggers ();
}

void benchmarkTriggersWithLogWithSave (const nomoLogFlag logFlag, const nomoLogPositionFlag logPositionFlag, const nomoFileFlag fileFlag){
    if (logFlag != logFlags[0]){
        int i;
        for (i=0;i<1000;i++)
            logFlags[i] = logFlag;
    }
    assumeWorldSquareXML ();
    saveWorldSquareXML (map);
    updateInputsWorldSquareXML ();
    benchmarkInputs ();
    nomoTriggersWithLog (logFlags, logPositionFlag, fileFlag);
}

static nomoCallback * benchmarkCallbacks;

void commandMotorWorldsquare (const float intensity, const float * data){
    commandMotorWorldSquareXML ((int)((1.0 - intensity) * 3.0), (short)data[COMMAND_MOTOR_WORLDSQUARE], (const commandMotor) abs((const int) data[COMMAND_MOTOR_WORLDSQUARE_VALUE]) % 5);
}

void commandSoundWorldsquare (const float intensity, const float * data){
    commandSoundWorldSquareXML ((int)((1.0 - intensity) * 3.0), (short)data[COMMAND_SOUND_WORLDSQUARE], abs((const int) data[COMMAND_SOUND_WORLDSQUARE_VALUE]) % 361);
}

void benchmarkInitialize (const char* dirMap, const short nbrAgents, const char* dirLog, const int dirLength){
    int i;
    logFlags = malloc(sizeof(nomoLogFlag) * 1000);
    benchmarkCallbacks = malloc(sizeof(nomoCallback) * 100);
    for (i=0;i<1000;i++)
        logFlags[i] = NOMO_NO_LOG;
    if (initializeWorldSquareXML(nbrAgents)){
        for(i=0;i<100;i+=2){
            benchmarkCallbacks[i] = &commandMotorWorldsquare;
            benchmarkCallbacks[i+1] = &commandSoundWorldsquare;
        }
        nomoInitialize(benchmarkCallbacks, dirLog, dirLength);
        memset(map, '\0', sizeof(map));
        strcpy(map, dirMap);
        readWorldSquareXML(map);
    }
}

void benchmarkFinalize (const nomoFinalizationFlag finalizationFlag){
    nomoFinalize(finalizationFlag);
    cleanWorldSquareXML();
    free(logFlags);
    free(benchmarkCallbacks);
}
