// UDPSender.cpp : Defines the entry point for the console application.
//

#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cstring>

#ifdef WIN32

#include <Winsock2.h>

#else

#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <unistd.h>
#define SOCKET  int

int closesocket(SOCKET s)
{
    return close(s);
}

#endif

bool socketlibinit()
{
#ifdef WIN32
    WSADATA wsaData;
    WORD wVersionRequested = MAKEWORD( 2, 2 );
    int err = WSAStartup( wVersionRequested, &wsaData );
    if ( err != 0 ) {
        /* Tell the user that we could not find a usable */
        /* WinSock DLL.                                  */
        return false;
    }

    /* Confirm that the WinSock DLL supports 2.2.*/
    /* Note that if the DLL supports versions greater    */
    /* than 2.2 in addition to 2.2, it will still return */
    /* 2.2 in wVersion since that is the version we      */
    /* requested.                                        */

    if ( LOBYTE( wsaData.wVersion ) != 2 ||
        HIBYTE( wsaData.wVersion ) != 2 ) {
            /* Tell the user that we could not find a usable */
            /* WinSock DLL.                                  */
            WSACleanup( );
            return false;
    }
#endif // WIN32

    return true;
}

enum Errors
{
    e_Unknown = -100,

    e_LibInit,
    e_InvalidParams,
    e_NoData
};

enum Params
{
    e_Executable,
    e_File,
    e_Port,
    e_IPAddress
};

int main(int argc, char* argv[])
{
    const char sampleNotifMsg[] = "*SAMPLE_NM*";
    if (argc < 3)
    {
        printf("USAGE: %s <filename> <port> [<ip address>]\n" , argv[e_Executable]);
        printf("<filename> content (up to 4K) will be sent to port at <ip address>\n");
        printf("<filename>: %s\n", sampleNotifMsg);
        return e_InvalidParams;
    }

    const char sampleNotifMsgData[] = {
	0x01, 0x06, 0x03, 0xc4, 0xaf, 0x87,
	0x64, 0x69, 0x67, 0x67, 0x65, 0x73, 0x74, 0x20, 0x20, 0x64, 0x69, 0x67, 0x67, 0x65, 0x73, 0x74,
	0x02, 0xD0, 0x00, 0x00, 0x00, 0x12, 0x34, 0x0A, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2E, 0x63,
	0x6F, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

	const char* msg = sampleNotifMsgData;
	size_t msg_size = sizeof(sampleNotifMsgData);
    const char* fileName = argv[1];

    std::vector<char> buffer;
    if (strcmp(fileName, sampleNotifMsg) != 0)
    {
        fileName = argv[e_File];
        FILE*   fileHandle = fopen(fileName, "rb");

        buffer.resize(4*1024);
		size_t r = fread(&buffer[0], 1, buffer.size(), fileHandle); 
		buffer.resize(r);
        
		
		fclose(fileHandle);

        msg = &buffer[0];
        msg_size = buffer.size();

    }

    if (msg_size == 0)
    {
        printf("There is no data to send. Please check the file: %s\n", fileName);
        return e_NoData;
    }


    if (!socketlibinit())
    {
        printf("FAILED to init socket library!\n");
        return e_LibInit;
    }

    SOCKET SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

    sockaddr_in RecvAddr;
    RecvAddr.sin_family = AF_INET;
    RecvAddr.sin_port = htons(atol(argv[e_Port]));

    const char* ipAddr = "127.0.0.1";
    if (argc >= 4)
    {
        ipAddr = argv[e_IPAddress];
    }
    RecvAddr.sin_addr.s_addr = inet_addr(ipAddr);

    sendto(SendSocket, msg, msg_size, 0,
        (sockaddr *) &RecvAddr, sizeof(RecvAddr));

    // When the application is finished sending, close the socket.
    printf("Finished sending file '%s' of total %d bytes. Closing socket.\n", fileName, msg_size);
    closesocket(SendSocket);

    //---------------------------------------------
    // Clean up and quit.
    printf("Exiting.\n");

#ifdef WIN32
    WSACleanup();
#endif // WIN32

	return 0;
}

