
#include "powertrace.h"
#include "contiki.h"
#include "net/rime.h"
#include "random.h"
#include "dev/button-sensor.h"
#include <stdlib.h>
#include "dev/leds.h"
#include <string.h>
#include <stdio.h>
#include "shell.h"
#include "serial-shell.h"
#include "collect-view.h"

static struct etimer et_hello;

/*
Ci-dessous, vous avez la definition de la structure "Broadcast_type" qui comporte 2 entier (id_diffusion et couleur)
qui vont nous permettre de de recuperer un message de difusion contenant un identifiant et une couleur. 
*/
struct Broadcast_type
{
    int id_diffusion;
    int couleur;
};
typedef struct Broadcast_type broadcast_type;

static struct broadcast_conn broadcast;
static void generer_couleur_de_blink(int code_couleur);
static char *decripter_code_couleur(int code_couleur);
static int id_dernier_message = 0;

PROCESS(example_broadcast_process, "[Exemple2] Exemple de diffusion");
AUTOSTART_PROCESSES(&example_broadcast_process);

/*
Ci-dessous, vous avez la definition de la fonction broadcast_recv;
Cette fonction analyse un paquet entrant et affiche le message et l'adresse de l'expéditeur. 
En la définissant comme fonction de rappel désignée de la diffusion, broadcast_recv est automatiquement appelée lors de la réception d'un paquet.
Cette fonction a 2 paramettre :
   - broadcast_conn *: cette structure qui a 2 structures: abc_conn, broadcast_callbacks *. 
   Abc_conn est le type de connexion de base sur lequel la connexion de diffusion est développée. 
   De plus, broadcast_callbacks pointe sur recv et les fonctions envoyées (dans cet exemple, recv seulement).

    - rimeaddr_t *: Ceci est une union qui a un tableau de caractères u8 [RIMEADDR_SIZE].
*/
static void broadcast_recv(struct broadcast_conn *c, const rimeaddr_t *from)
{

    broadcast_type *message_recu; // declaration de pointeur de type broadcast_type sur message recu
    message_recu = packetbuf_dataptr(); // affectation du message recu a "message_recu"

    printf(" Message recu depuis %d.%d: ’%d;%s’\n", from->u8[0], from->u8[1], message_recu->id_diffusion, decripter_code_couleur(message_recu->couleur));
    printf(" Message recu :’%d;%s’\n", message_recu->id_diffusion, decripter_code_couleur(message_recu->couleur));
    printf("  - id recu : ’%d’\n", message_recu->id_diffusion);
    printf("  - couleur recu : ’%s’\n", decripter_code_couleur(message_recu->couleur));
    printf("ID: ’%d,%d’\n", id_dernier_message, message_recu->id_diffusion);

    if (message_recu->id_diffusion != id_dernier_message)
    {
        id_dernier_message = message_recu->id_diffusion;
        generer_couleur_de_blink(message_recu->couleur);
        printf("Allumage de la LED %s\n", decripter_code_couleur(message_recu->couleur));

        packetbuf_copyfrom(message_recu, 7);
        broadcast_send(&broadcast);
        printf("Envoi du message : %d;%s\n", message_recu->id_diffusion, decripter_code_couleur(message_recu->couleur));
    }

}

static const struct broadcast_callbacks broadcast_call = {broadcast_recv};

PROCESS_THREAD(example_broadcast_process, ev, data)
{
    static struct etimer et;
    PROCESS_EXITHANDLER(broadcast_close(&broadcast);)

    PROCESS_BEGIN();
/* Commencez powertracing, une fois toutes les 50 secondes. */
  /*
    powertrace_start(CLOCK_SECOND * 20);

    serial_shell_init();
    shell_reboot_init();
     shell_rime_init();
     shell_rime_netcmd_init();
     shell_powertrace_init();
     shell_text_init();
     shell_time_init();
    shell_collect_view_init();
*/
    broadcast_open(&broadcast, 129, &broadcast_call);

    while (1)
    {
        etimer_set(&et_hello, CLOCK_SECOND * 20); // attendre 20 secondes entre chaque reception de messages
        PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
    }
    PROCESS_END();
}

/*
Ci-dessous, vous avez la fonction "generer_couleur_de_blink" qui permet 
de generer des couleurs de leds en fonction de son code  comme suit  1 = bleu , 2 = vert, 3 = rouge.
cette fonction prend en paramettre un entier qui est le code de couleur et allume la LED corespondante.
*/
static void generer_couleur_de_blink(int code_couleur)
{
    leds_off(LEDS_ALL);
    switch (code_couleur)
    {
    case 1:
        leds_on(LEDS_BLUE);
        break;
    case 2:
        leds_on(LEDS_GREEN);
        break;
    case 3:
        leds_on(LEDS_RED);
    default:
        break;
    }
}

/*
Ci-dessous, vous avez la fonction "decripter_code_couleur" qui permet 
de decripter un code de couleur passer en paramettre puis retourne sa couleur comme suit  1 = "bleu" , 2 = "vert", 3 = "rouge".
*/
static char *decripter_code_couleur(int code_couleur)
{
    switch (code_couleur)
    {
    case 1:
        return "bleu";
        break;
    case 2:
        return "vert";
        break;
    case 3:
        return "rouge";
    }
    return "vert";
}
