/* 
 * File:   interfaz.cpp
 * Author: maximus
 *
 * Created on 19 November 2008, 2:52 AM
 */


#include "Mz-Sens.h"


bool MZQuit = false;
itfzContainer* Contenedor;
bool MZMotorRuning = false;
int MOUSEx = 0;
int MOUSEy = 0;
bool MOUSE1 = false;
bool MZTUSD = false;
bool MZTPSD = false;

void MZSQuit() {
    MZTPSD = true;
    MZTUSD = true;
    SDL_WaitThread(itfzUpdaterThread, NULL);
    MZNetShutDown();
    MZQuit = true;
    //Destroy mutex
    SDL_DestroyMutex(itfzWriteLock);
    SDL_DestroyMutex(itfzRXBuffLock);
    SDL_DestroyMutex(itfzTXBuffLock);

    //Free the surfaces


    //Quit SDL
    SDL_Quit();
}
bool mzsinside(SDL_Rect sq, int x, int y) {
    if ((x >= sq.x) && (x <= (sq.x + sq.w) && (y >= sq.y) && (y < (sq.y + sq.h))))
        return (true);
    else return (false);
}

void mzsEventHdlr(void) {
    SDL_Event event;
    SDL_GetMouseState(&MOUSEx, &MOUSEy);
    SDL_PollEvent(&event);
    switch (event.type) {
            /*case SDL_MOUSEMOTION:
                printf("Mouse moved by %d,%d to (%d,%d)\n",
                        event.motion.xrel, event.motion.yrel,
                        event.motion.x, event.motion.y);
                break;*/
        case SDL_MOUSEBUTTONDOWN:
            if (event.button.button == 1)
                MOUSE1 = true;
            for (int j = 0; j < Contenedor->clicks.size(); j++)
                if (mzsinside(Contenedor->clicks.at(j)->area, event.button.x, event.button.y)) {
                    Contenedor->clicks.at(j)->clickhandler(event.button.x, event.button.y);
                    break;
                }
            break;
        case SDL_MOUSEBUTTONUP:
            if (event.button.button == 1)
                MOUSE1 = false;
            for (int j = 0; j < Contenedor->clicks.size(); j++)
                if (Contenedor->clicks.at(j)->clicked) {
                    Contenedor->clicks.at(j)->unclickhandler();
                    break;
                }
            break;
        case SDL_QUIT:
            MZSQuit();
            break;
        default:
            MOUSE1 = false;
    }
}

int itfz_Updater(void *data) {
    int tick = 0;
    int gLastTick = 0;
    int commandEnding;
    int up = 0;
    string ID;
    string rxID;
    float rxValue;
    int rxLimiter;
    string comando;
    int i;
    char letrita = 0; // BORRAR
    bool flipflop = true;
    while (!MZTUSD) {
        tick = SDL_GetTicks();


        SDL_mutexP(itfzRXBuffLock);
        while (MZnetQueuedCommands) {
            commandEnding = MZnetBufferRx.find('\n');
            comando = MZnetBufferRx.substr(0, commandEnding);
            if (comando == "OK") {
                MZInit();
            }
            //==============BORRAR
            cout << "=>" << comando << "<=" << endl;
            //==============
            MZnetBufferRx.erase(0, commandEnding + 1);
            MZnetQueuedCommands--;
            SDL_mutexP(itfzWriteLock);

            rxLimiter = comando.find('~');
            rxID = comando.substr(0, rxLimiter);
            rxValue = atof(comando.substr(rxLimiter + 1).c_str());

            for (int j = 0; j < Contenedor->updates.size(); j++)
                if (strcmp((Contenedor->updates.at(j)->ID).c_str(), rxID.c_str()) == 0) {
                    Contenedor->updates.at(j)->value = rxValue;
                    break;
                }
            SDL_mutexV(itfzWriteLock);
        }
        SDL_mutexV(itfzRXBuffLock);

        gLastTick = SDL_GetTicks();
        if (gLastTick - tick <= 200)
            SDL_Delay(200 - (gLastTick - tick));
    }

    return 0;
}

int itfz_Painter(void *data) {
    int tick = 0;
    int gLastTick = 0;
    int commandEnding;

    while (!MZTPSD) {
        tick = SDL_GetTicks();


        SDL_mutexP(itfzWriteLock);
        for (int j = 0; j < Contenedor->components.size(); j++)
            Contenedor->components.at(j)->paint();
        SDL_mutexV(itfzWriteLock);
        Contenedor->flipscreen();

        gLastTick = SDL_GetTicks();
        if (gLastTick - tick <= 50)
            SDL_Delay(50 - (gLastTick - tick));
    }

    return 0;
}

void MZInit(void) {
    SDL_Delay(500);
    MZnetSend("tson");
    //MZnetSend("acel" + 34);
}

int main(int argc, char* args[]) {
    int tick = 0;
    int gLastTick = 0;
    Contenedor = itfz_Init(); // Inicializa SDL y crea el contenedor principal    
    itfzWriteLock = SDL_CreateMutex();
    itfzTXBuffLock = SDL_CreateMutex();
    itfzRXBuffLock = SDL_CreateMutex();

    itfzNetThreadRcv = SDL_CreateThread(MZnetThreadRcv, NULL);
    if (itfzNetThreadRcv == NULL) {
        printf("No es posible crear el thread de recepcion: %s\n", SDL_GetError());
        exit(EXIT_FAILURE);
    }
    itfzNetThreadSnd = SDL_CreateThread(MZnetThreadSnd, NULL);
    if (itfzNetThreadSnd == NULL) {
        printf("No es posible crear el thread de transmision: %s\n", SDL_GetError());
        exit(EXIT_FAILURE);
    }
    itfzUpdaterThread = SDL_CreateThread(itfz_Updater, NULL);
    if (itfzUpdaterThread == NULL) {
        printf("No es posible crear el thread de actualizacion: %s\n", SDL_GetError());
        exit(EXIT_FAILURE);
    }
    itfzPainterThread = SDL_CreateThread(itfz_Painter, NULL);
    if (itfzUpdaterThread == NULL) {
        printf("No es posible crear el thread de dibujo: %s\n", SDL_GetError());
        exit(EXIT_FAILURE);
    }
    while (!MZQuit) {
        tick = SDL_GetTicks();
        gLastTick = SDL_GetTicks();
        mzsEventHdlr();
        if (gLastTick - tick <= 300)
            SDL_Delay(100 - (gLastTick - tick));

    }
    return 0;
}

