#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <glob.h>
#include <lcm/lcm-cpp.hpp>
#include "lcmMessages/Event.hpp"

/** Return syntactically greatest file matching speccified file name pattern */
char *latestFilename(char *pattern);

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

  if (argc != 4) {
    fprintf(stderr, "usage: %s logfile tag channelName\n", argv[0]);
    fprintf(stderr, "Monitors ascii logfile, publishes lines that contain tag to LCM channelName\n");
    return 1;
  }

  char *filenameBase = argv[1];
  char *lineTag = argv[2];
  char *channelName = argv[3];

  lcm::LCM lcm;
  if (!lcm.good()) {
    fprintf(stderr, "Error connecting to LCM\n");
    return 1;
  }

  // Look for files that begin with specified pattern
  char pattern[256];
  sprintf(pattern, "%s*", filenameBase);
  char *latest = latestFilename(pattern);
  if (latest == NULL) {
    fprintf(stderr, "No files matching \"%s\"\n", pattern);
    return 1;
  }

  char filename[256];
  strcpy(filename, latest);
  
  // Open the file
  fprintf(stderr, "Opening latest file, \"%s\"\n", filename);
  FILE *input = fopen(filename, "r");
  if (input == NULL) {
    fprintf(stderr, "Couldn't open file \"%s\"\n", filename);
    return 1;
  }
  // Disable buffering
  setbuf(input, NULL);

  // Allocate line 
  size_t nBytes = 256;
  char *line = (char *)malloc(nBytes);
  lcmMessages::Event event;

  // Read each full line
  while (true) {
    if (getline(&line, &nBytes, input) != -1) {
      fprintf(stderr, "Got line: %s", line);
      // If line contains designated tag, publish full line to LCM
      if (strstr(line, lineTag) != NULL) {
	if (line[strlen(line)-1] == '\n') {
	  // Strip off ending newline
	  line[strlen(line)-1] = '\0';
	}
	fprintf(stderr, "publish \"%s\"\n", line);
	std::string str(line);
	event.epochSec = time(NULL);
	event.eventMsg = str;
	lcm.publish(channelName, &event);
      }
    }
    else {
      // No new data in file
      // Newer file available yet?
      latest = latestFilename(pattern);
      if (latest == NULL) {
	fprintf(stderr, "No files matching \"%s\"\n", pattern);
	return 1;
      }
      // printf("filename: %s  latest: %s\n", filename, latest);
      if (strcmp(latest, filename) != 0) {
	// There is a new "latest" file
	// Close existing file and open it
	fclose(input);
	strcpy(filename, latest);
	// Open latest file
	fprintf(stderr, "Opening latest file, \"%s\"\n", filename);
	input = fopen(filename, "r");
	if (input == NULL) {
	  fprintf(stderr, "Couldn't open file \"%s\"\n", filename);
	  return 1;
	}
	// Disable buffering
	setbuf(input, NULL);
      }
      else {
	// printf("%s - No new file yet\n", filename);
	// Sleep a bit
	usleep(100000);
      }
    }
  }
  fprintf(stderr, "Done reading %s\n", filename);
  return 0;
}

/** Return syntactically greatest file matching speccified name pattern */
char *latestFilename(char *pattern) {
  static char latestFilename[256];

  char *retVal = NULL;
  glob_t globBuf;
  if (!glob(pattern, 0, NULL, &globBuf)) {
    // List matching files
    // printf("files matching %s:\n", pattern);
    for (int i = 0; i < (int )globBuf.gl_pathc; i++) {
      // printf("file: %s\n", globBuf.gl_pathv[i]);
    }
    
    strcpy(latestFilename, globBuf.gl_pathv[globBuf.gl_pathc-1]);
    retVal = latestFilename;
  }
  else {
    fprintf(stderr, "No files match %s\n", pattern);
  }

  globfree(&globBuf);
  return retVal;
}

