#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <ctype.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define PORT                        10000           //PORT ADDRESS
#define FITS_HEADER_SIZE            16384           //FITS HEADER SIZE
#define ACKNOWLEDGE_SIZE            100

#define END_MSG_CHAR                '\n'
#define END_MSG_STRING              "\n"

#define ACQUISITION_CMD             "ACQ"     
#define END_ACQUISITION_CMD         "END_ACQ" 

#define ACKNOLEDGE_RECEPTION        "DATA RECEIVED" 
#define ACKNOLEDGE_EXECUTION_OK     "OK"      
#define ACKNOLEDGE_EXECUTION_ERR    "ERROR"   

#define SUCCESS                     1
#define FAILURE                     0

#define TRUE                        1
#define FALSE                       0

#define HOST                        "zeus"

#define DEBUG_MODE                  FALSE


int dpsmSendHeader(char *buffer)
{
    char    ack[ACKNOWLEDGE_SIZE];    //FITS HEADER
    int     sd;                       //SOCKET DESCRIPTOR
    struct  sockaddr_in pin;          //BORDEL POUR SOCKET
    struct  hostent     *hp;
    int     received;
    int     i;
    int     position = 0;
    int     foundEndMsg = FALSE;

    //Find the server
    if ((hp = gethostbyname(HOST)) == 0)
    {
        perror("FATAL ERROR:\t\t");
        return(FAILURE);
    }

    //FILL the socket structure with host information
    bzero(&pin, sizeof(pin));
    pin.sin_family = AF_INET;
    pin.sin_addr = *(struct in_addr *)(hp->h_addr);
    pin.sin_port = htons(PORT);

    //Get an internet socket 
    if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("FATAL ERROR:\t\t");
        close(sd);
        exit(FAILURE);
    }

    //Connect to PORT on HOST
    if (connect(sd, (struct sockaddr *) &pin,sizeof(pin)) == -1)
    {
        perror("FATAL ERROR:\t\t");
        close(sd);
        exit(FAILURE);
    }
    if (DEBUG_MODE == TRUE)
    printf("INFORMATION:\tConnection with slave established\n");

    //Send a message
    if (send(sd, buffer, strlen(buffer), 0) == -1)
    {
        perror("FATAL ERROR:\t\t");
        close(sd);
        exit(FAILURE);
    }

    //Send message End
    if (send(sd, END_MSG_STRING, 1, 0) == -1)
    {
        perror("FATAL ERROR:\t\t");
        close(sd);
        exit(FAILURE);
    }

    
    if (DEBUG_MODE == TRUE)
    {
        printf("INFORMATION:\tMessage to slave sent(%d char)\n",
               strlen(buffer));
    }
    //Check if the transmission is ended
    while (foundEndMsg == FALSE)
    {
        //Initialize reception buffer
        memset(&ack[0],NULL,ACKNOWLEDGE_SIZE*sizeof(char));

        //Get the data reception acknowledge from the client
        if((received = recv(sd, ack, ACKNOWLEDGE_SIZE, MSG_PEEK)) == -1)
        {
            perror("FATAL ERROR:\t\t");
            close(sd);
            exit(FAILURE);
        }
        i=0;
        while((i < received) && (foundEndMsg == FALSE))
        {   
            if (ack[i] == END_MSG_CHAR)
            {
                position = i;
                foundEndMsg = TRUE;
            }
            i++;
        }
    }


    //Initialize reception buffer
    memset(&ack[0],0,ACKNOWLEDGE_SIZE*sizeof(char));

    //Get the data reception acknowledge from the client
    if((recv(sd, ack, position+1, 0)) == -1)
    {
        perror("FATAL ERROR:\t\t");
        close(sd);
        exit(FAILURE);
    }
    ack[position] = NULL;
    

    if (DEBUG_MODE == TRUE)
    printf("INFORMATION:\tReception of the slave acknowledge : '%s'\n",
           ack);
    
    //Check the acknowledge message
    if(strcmp(ack, ACKNOLEDGE_RECEPTION) != 0)
    {
        printf("ERROR:\t\tTHE DPSM PC CLIENT REPLY A STRANGE MESSAGE: '%s'\n",
               ack);
        close(sd);
        return FAILURE;
    }
    foundEndMsg = FALSE;
    //Check if the transmission is ended
    while (foundEndMsg == FALSE)
    {
        //Initialize reception buffer
        memset(ack,0,ACKNOWLEDGE_SIZE*sizeof(char));

        //Get the data reception acknowledge from the client
        if((received = recv(sd, ack, ACKNOWLEDGE_SIZE, MSG_PEEK)) == -1)
        {
            perror("FATAL ERROR:\t\t");
            close(sd);
            exit(FAILURE);
        }

        i=0;
        while((i < received) && (foundEndMsg == FALSE))
        {   
            if (ack[i] == END_MSG_CHAR)
            {
                position = i;
                foundEndMsg = TRUE;
            }
            i++;
        }
    }

    //Initialize reception buffer
    memset(ack,0,ACKNOWLEDGE_SIZE*sizeof(char));

    //Get the data completion acknowledge from the client
    if((recv(sd, ack, position+1, 0)) == -1)
    {
        perror("FATAL ERROR:\t\t");
        close(sd);
        exit(FAILURE);
    }
    ack[position] = NULL;

    if (DEBUG_MODE == TRUE)
    printf("INFORMATION:\tClient result acknowledge : '%s' \n", ack);

    //Check the acknowledge message
    if (strcmp(ack,ACKNOLEDGE_EXECUTION_ERR) == 0)
    {
        printf("ERROR:\t\tTHE DPSM PC CLIENT HAS RETURNED AN ERROR '%s'\n",
               ack);
        close(sd);
        return(FAILURE);
    }

    if (strcmp(ack, ACKNOLEDGE_EXECUTION_OK) == 0)
    {
        close(sd);
        return(SUCCESS);
    }
    else
    {
        printf("ERROR:\t\tTHE DPSM PC CLIENT REPLY A NOT UNDERSTANDABLE MESSAGE: '%s'\n", ack);
        close(sd);
        return(FAILURE);
    }
}

