/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
 * are also available at http://curl.haxx.se/docs/copyright.html.
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 * copies of the Software, and permit persons to whom the Software is
 * furnished to do so, under the terms of the COPYING file.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <locale.h>

#include <curl/curl.h>

struct MemoryStruct {
  char *memory;
  size_t size;
};

static size_t
WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
  size_t realsize = size * nmemb;
  struct MemoryStruct *mem = (struct MemoryStruct *)userp;
 
  mem->memory = realloc(mem->memory, mem->size + realsize + 1);
  if (mem->memory == NULL) {
    /* out of memory! */ 
    printf("not enough memory (realloc returned NULL)\n");
    exit(EXIT_FAILURE);
  }
 
  memcpy(&(mem->memory[mem->size]), contents, realsize);
  mem->size += realsize;
  mem->memory[mem->size] = 0;
 
  return realsize;
}

int connectAtPort(const char *machine, int port)
{
  int sd;
  struct hostent *hp;
  struct sockaddr_in server;
 
  memset((char *)&server, 0, sizeof(struct sockaddr_in));
  
  server.sin_family = AF_INET;
  server.sin_port = htons((u_short)port);

  if (isdigit(machine[0])) {
    server.sin_addr.s_addr = inet_addr(machine);
  } else {
    if ((hp = gethostbyname((char *)machine)) == (struct hostent *)NULL) {
      return -1;
    }
    memcpy((char *)&server.sin_addr, (char *)hp->h_addr,  hp->h_length);
  }
  
  if ((sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
    return -1;
  }
  
  if (connect(sd, (struct sockaddr *)&server, sizeof(server)) < 0) {
    return -1;
  }

  return sd;
}

int main(void)
{
  CURL *curl;
  CURLcode res;
  struct MemoryStruct chunk;

  curl = curl_easy_init();
  if(curl) {

    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);

    /* Perform the request, res will get the return code */
    chunk.memory = malloc(1); chunk.size = 0;
    curl_easy_setopt(curl, CURLOPT_URL, "https://odss.mbari.org/odss/services/track/read?platformID=3439&returnSRS=4326&lastNumberOfFixes=1&returnFormat=csv");
    res = curl_easy_perform(curl);

    if (res == CURLE_OK) {
      char gllStr[128];
      char *pch;
      double longitude, latitude;
      struct tm fixTime;
      int field = 1;
      char *rval;

      pch = strtok(chunk.memory, ",\r\n");
      while (pch != NULL) {
	if (field == 4){
	  tzset();
	  memset(&fixTime, 0, sizeof(struct tm));
	  rval = strptime(pch, "%FT%T%H:%M:%OS%Oz", &fixTime);
	  if (rval == NULL) printf("parsed time\n");
	  time_t mytime = mktime(&fixTime);
	  printf("time is %s\n", asctime(gmtime(&mytime)));
	}
	if (field == 5) longitude = strtod(pch, NULL);
	if (field == 6) latitude = strtod(pch, NULL);
	field++;
	pch = strtok(NULL,",\r\n");
      }

      printf("lat is %f\n", latitude);
      printf("lon is %f\n\n", longitude);

      char latH, lonH;
      if (latitude < 0) {
	latH = 'S';
      } else {
	latH = 'N';
      }

      if (longitude < 0) {
	lonH = 'W';
      } else {
	lonH = 'E';
      }

      longitude = fabs(longitude);
      latitude = fabs(latitude);
      int latD, lonD;
      double latM, lonM;

      latD = trunc(latitude);
      latM = fmod(latitude*60.0, 60.0);
      lonD = trunc(longitude);
      lonM = fmod(longitude*60.0, 60.0);

      sprintf(gllStr, "$GPGLL,%2d%2.6f,%c,%3d%2.6f,%c,074023.00,A*00\n",
	      latD,latM,latH,lonD,lonM,lonH);
      printf("%s\n", gllStr);

      //clean up memory
      free(chunk.memory);
      int socket = connectAtPort("134.89.32.102",14010);
      write(socket, gllStr, strlen(gllStr));
      close(socket);
    }

    /* Check for errors */
    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s\n",
              curl_easy_strerror(res));

    /* always cleanup */
    curl_easy_cleanup(curl);
  }
  return 0;
}
