#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>

#include <string.h>

#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

#define BUFSIZE 32

struct options {
    char *port;
    char *hostname;
};

void *conexion_televisor(void *ptr);

int main (int argc, char *argv[]) {

    if (argc != 4) {
        if ( (argc == 2) && (strcmp(argv[1], "--help") == 0) ) {
            printf("Sintaxis:\n");
            printf("\t%s <servidor_acumulador> <puerto_votacion> <numero_clientes_simulados>\n\n", argv[0]);
            printf("Parametros:\n");
            printf("<servidor_acumulador>         Direccion IP del servidor acumulador\n");
            printf("<puerto_votacion>             Puerto en que el servidor recibe conexiones de televisores\n");
            printf("<numero_clientes_simulados>   Numero de televisores generados para la simulacion\n");
        }
        else {
            printf("Usage: %s <servidor_acumulador> <puerto_votacion> <numero_clientes_simulados>\n", argv[0]);
            printf("Try '%s --help' for more information\n", argv[0]);
        }
        exit(1);
    }

    struct options op;
    int i, repeat;

    // Seteo de parametros necesarios para cada televisor
    op.port = argv[2];
    op.hostname = argv[1];
    repeat = atoi(argv[3]);
    pthread_t thread[repeat];

    // Generacion de nueva semilla para numeros aleatorios
    srand(time(NULL));

    printf("Iniciando test de Esfuerzo...\n");

    // Creacion de hebras para cada televisor
    for ( i = 0; i < repeat; i++)
        pthread_create(&thread[i], NULL, conexion_televisor, (void *)&op);

    for ( i = 0; i < repeat; i++)
        pthread_join(thread[i], NULL);

    printf("Done\n");

    return 0;
}

// Funcion que ejecuta el programa "televisor"

void *conexion_televisor(void *ptr) {

    struct options op;
    pid_t pid;
    int status;
    char buf[BUFSIZE];

    op = *(struct options *)ptr;

    // Generacion de la opcion de forma aleatoria
    sprintf(buf, "%d", (rand() % 6));

    // Creacion de proceso hijo
    if ((pid = fork()) < 0) {
        perror("fork");
        exit(1);
    }

    // Proceso hijo
    if (pid == 0) {
        execlp("televisor", "televisor", op.hostname, op.port, buf , NULL);
        perror("exec");
        exit(-1);
    }

    waitpid(pid, &status, 0);
    pthread_exit(NULL);
}
