// #include "ap_config.h"

#ifdef _WIN32
#include "windows.h"
#endif

#include <cstdio>
#include <cstdlib>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <algorithm>

// #include <ctype.h>

// #include "setilib.h"
// #include "db_table.h"
// #include "sqlhdr.h"
// #include "schema_master.h"
// #include "seti_doppler.h"
#include "parse.h"
#include "xml_util.h"
#include "db_table.h"
#include "ap_schema.h"
// #include "astropulse.h"
#include "util.h"
#include "base64.h"
#include "ap_raw_data_db.h"
#undef read

#include <cstring>
#include <cassert>
#include <cstdlib>
#include <cstdio>
#include <cerrno>
#include <ctime>
#include <cmath>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

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

// Handle command line arguments

bool count = false;
bool result = false;
bool workunit = false;
bool tape = false;
bool waterfall = false;
bool dedisperse = false;
bool timeseries = false;
bool lcgammplot = false;
bool have_where_clause = false;
int fftlen = 64;
int first = 0;
int picwidth = 640;
int picheight = 480;
int width = 0;
char * db_name = "apb_db@sci_master_tcp";  // will change later if found in command line

char c_string[256];
std::string where_clause = "";

/* Possible arguments:
 *  -count	select count(*), the number of signals that fit the query
 *  -result	join the result table to ap_signal
 *  -workunit	join the workunit table to ap_signal (as well as result)
 *  -tape	join the tape table to ap_signal (as well as result and workunit)
 *  -dedisperse view the plot in dedispersed mode
 *  -timeseries view the plot as a time series
 *  -lcgammplot view the plot as a time series, scaled like the log of the gamma function
 *  -firstN  	select the first N signals from the database
 *  -db_name	the name of the database we'll be connecting to.
 */
for (int i=1; i<argc; i++) {
    if (!strcmp(argv[i], "-count")) {
      count = true;
      fprintf(stderr, "counting signals instead of displaying\n");
    }
    else if (!strcmp(argv[i], "-result")) {
      result = true;
      fprintf(stderr, "joining with result\n");
    }
    else if (!strcmp(argv[i], "-workunit")) {
      workunit = true;
      fprintf(stderr, "joining with result, workunit\n");
    }
    else if (!strcmp(argv[i], "-tape")) {
      tape = true;
      fprintf(stderr, "joining with result, workunit, tape\n");
    }
    else if (!strcmp(argv[i], "-waterfall")) {
      waterfall = true;
      fprintf(stderr, "showing waterfall plots\n");
    }
    else if (!strcmp(argv[i], "-dedisperse")) {
      dedisperse = true;
      fprintf(stderr, "showing dedispersed waterfall plots\n");
    }
    else if (!strcmp(argv[i], "-timeseries")) {
      timeseries = true;
      fprintf(stderr, "showing time series plots\n");
    }
    else if (!strcmp(argv[i], "-lcgammplot")) {
      lcgammplot = true;
      fprintf(stderr, "showing log gamma plots\n");
    }
    else if (!strncmp(argv[i], "-width", 6)) {
      width = atoi(argv[i] + 6);
      fprintf(stderr, "Plot width: %d", width);
    }
    else if (!strncmp(argv[i], "-fftlen", 7)) {
      fftlen = atoi(argv[i] + 7);
      fprintf(stderr, "fftlen: %d", fftlen);
    }
    else if(!strncmp(argv[i], "-picwidth", 9)) {
      picwidth = atoi(argv[i] + 9);
      fprintf(stderr, "Picture width: %d", picwidth);
    }
    else if(!strncmp(argv[i], "-picheight", 10)) {
      picheight = atoi(argv[i] + 10);
      fprintf(stderr, "Picture height: %d", picheight);
    }
    else if (!strncmp(argv[i], "-first", 6)) {
      first = atoi(argv[i] + 6);
      fprintf(stderr, "Selecting first %d ap_signals\n", first);
    }
    else if (!strncmp(argv[i], "-db_name", 8)) {
      db_name = argv[i] + 8;
      fprintf(stderr, "Running with db %s\n", db_name);
    }
    else {  // where clause
      if(have_where_clause) {
        fprintf(stderr, "In query_to_html : too many undashed or unrecognized args.  (Should only be a where clause.)  Usage: query_to_html where_clause [-count] [-result] [-workunit] [-tape] [-dedisperse] [-timeseries] [-lcgammplot] [-firstN] [-fftlenN] [-picwidthN] [-picheightN]<br>\n");
        exit(-1);
      }
      sprintf(c_string, "where %s", argv[i]);
      where_clause = c_string;      
      have_where_clause = true;
    }
}

if(width > 65528) {
  printf("In query_to_html : width must be <= 65528\n");
  exit(-1);
}

if(have_where_clause == false) {
  fprintf(stderr, "In query_to_html : no where clause.  Usage: query_to_html where_clause [-count] [-result] [-workunit] [-tape] [-dedisperse] [-timeseries] [-lcgammplot] [-firstN]<br>\n");
  exit(-1);
}

if(first <= 0) {
  printf("Error: we currently require first > 0\n");
  exit(-1);
}

setenv("INFORMIXDIR", "/disks/thumper/a/apps/informix", 1);
setenv("INFORMIXSQLHOSTS", "/disks/thumper/a/apps/informix/etc/sqlhosts", 1);
setenv("INFORMIXSERVER", "sci_master_tcp", 1);

int retval = db_change(db_name);
fprintf(stderr, "db_change(%s) returns %d\n", db_name, retval);

ap_signal this_ap_signal;
// open_query( where clause, order by, directives )
this_ap_signal.open_query(where_clause, "", "{--+first_rows}");
// this_ap_signal.open_query(where_clause);

if(workunit || result || tape) {
  printf("In query_to_html : no support yet for joins.  Use a nested select statement instead.<br>\n");
  exit(-1);
}

// Open the html file
char html_filename[256];
long create_time = time(NULL);
sprintf(html_filename, "ap_signals_%ld.html", create_time);
FILE * html_file = fopen(html_filename, "w");
if(!html_file) {
  printf("In query_to_html : error opening file %s for write.<br>\n", html_filename);
  exit(-1);
}

// Write to the html file
fprintf(html_file, "<html>\n");
fprintf(html_file, "<head>\n<title>");
if(count) fprintf(html_file, "Count ");
else fprintf(html_file, "Plots ");
fprintf(html_file, "of ap_signals with where_clause = \"%s\"", where_clause.c_str());
fprintf(html_file, "</title>\n</head>\n<body>\n");

if(count) fprintf(html_file, "Count ");
else fprintf(html_file, "Plots ");
fprintf(html_file, "of ap_signals with where_clause = \"%s\"<br>\n<br>\n", where_clause.c_str());
fprintf(html_file, "Extracted from database %s<br>\n<br>\n", db_name);
fprintf(html_file, "Width in samples: %d<br>\n<br>\n", width);


FILE * waterfall_jpg;
FILE * waterfall_txt;
char idlcstring[1000];
char dedispcstring[30];
char timeseriescstring[30];
char lcgammplotcstring[30];
char fftlencstring[30];

// Loop through the signals, generating mini wu files and adding to the html as you go.
int num = 0;
while (retval = this_ap_signal.get_next()) {
  // bookkeeping
  if(first && num >= first) break;

  // min bytes to write
  int min_bytes = 16382;
  if(this_ap_signal.raw_data.size() >= min_bytes) 
    num++;
  else
    continue;
  if(count) continue; // don't plot it, just count

  // make plots
  std::string wufilename = "unknown_wu";
  if(Astropulse::ap_signal_to_miniwufile(this_ap_signal, wufilename, 1, "")) {
    printf("In query_to_html : error in ap_signal_to_miniwufile.<br>\n");
    exit(-1);
  }
  
  // Append to html file
  fprintf(html_file, "<H4>ap_signal: id %d, peak_power %f, dm %d, scale %d</H3><br><br>\n",
		this_ap_signal.id, this_ap_signal.peak_power, this_ap_signal.dm, this_ap_signal.scale);

  for(int plot_type = 0; plot_type <= 3;  plot_type++) {

    if(plot_type == 0) {
      if(!waterfall) continue;
      fprintf(html_file, "Waterfall plot:<br>\n<br>\n");
    }
    else if(plot_type == 1) {
      if(!dedisperse) continue;
      fprintf(html_file, "Dedispersed plot:<br>\n<br>\n");
    }
    else if(plot_type == 2) {
      if(!timeseries) continue;
      fprintf(html_file, "Time series:<br>\n<br>\n");
    }
    else if(plot_type == 3) {
      if(!lcgammplot) continue;
      fprintf(html_file, "Log incomplete gamma plot:<br>\n<br>\n");
    }

    if(plot_type == 0 || plot_type == 1 || plot_type == 2 || plot_type == 3) {

      // Write waterfall.txt
      waterfall_txt = fopen("waterfall.txt", "w");
      if(!waterfall_txt) {
        printf("In query_to_html : error opening file waterfall.txt for write.<br>\n");
        exit(-1);
      }
      fprintf(waterfall_txt, "!PATH += \":~vonkorff/build/Josh_idl_files/analysis_July_08\"\n");
      fprintf(waterfall_txt, ".run waterfall.pro\n");

      // Write waterfall.txt: prepare dedisp
      if (plot_type == 0)
        sprintf(dedispcstring, "");
      else if (plot_type == 1 || plot_type == 2 || plot_type == 3)
        sprintf(dedispcstring, " dedisp = %d, ", this_ap_signal.dm);

      if (plot_type == 0 || plot_type == 1 || plot_type == 3)
        sprintf(timeseriescstring, "");
      else if (plot_type == 2)
        sprintf(timeseriescstring, " /timeseries, ");
      
      if (plot_type == 0 || plot_type == 1 || plot_type == 2)
        sprintf(lcgammplotcstring, "");
      else if (plot_type == 3)
        sprintf(lcgammplotcstring, " /lcgammplot, ");

      if (plot_type == 0 || plot_type == 1 || plot_type == 2)
        sprintf(fftlencstring, " fftlen = %d, ", fftlen);
      else if (plot_type == 3)
        sprintf(fftlencstring, " fftlen = %d, ", (int) (pow(2.0, (double) this_ap_signal.scale) + 0.01));

      // Write waterfall.txt: construct idlstring
      sprintf(idlcstring, "waterfall, center=32768, width=%d, file=\"unknown_wu_0.mwu\", /physical, /zbuffer, databytes=16384, jpgname=\"/disks/ptolemy/c/home/boincadm/public_html/plots/waterfall.jpg\", %s %s %s %s /nokbrd, /mini\n", width, dedispcstring, timeseriescstring, lcgammplotcstring, fftlencstring);

      fprintf(waterfall_txt, "%s", idlcstring);
      fclose(waterfall_txt);

      // This is suppose do capture stderr from waterfallscript, discard stdout .. not sure it was working
      // if(system("sh -c '/disks/ptolemy/c/home/boincadm/public_html/waterfallscript 2>&1 1>/dev/null'"))  
      // if(system("/disks/ptolemy/c/home/boincadm/public_html/waterfallscript 2>& /dev/null")) 
      
      if(system("/disks/ptolemy/c/home/boincadm/public_html/waterfallscript > /dev/null")) {
        printf("In query_to_html : error when running waterfallscript<br>\n");
        exit(-1);
      }

      // mv waterfall.jpg
      waterfall_jpg = fopen("plots/waterfall.jpg", "r");
      if(!waterfall_jpg) {
        printf("In query_to_html : error opening file %s for read (need to move it.)<br>\n", "plots/waterfall.jpg");
        exit(-1);
      }
      fclose(waterfall_jpg);
      char waterfall_mv[256];
      if(plot_type == 0) {
        sprintf(waterfall_mv, "mv plots/waterfall.jpg plots/waterfall_ap_signal_%d.jpg", this_ap_signal.id);
        fprintf(html_file, "<img src=\"plots/waterfall_ap_signal_%ld.jpg\" width=%d height=%d><br><br>\n", (int) this_ap_signal.id, picwidth, picheight);
      } else if(plot_type == 1) {
        sprintf(waterfall_mv, "mv plots/waterfall.jpg plots/dedisperse_ap_signal_%d.jpg", this_ap_signal.id);
        fprintf(html_file, "<img src=\"plots/dedisperse_ap_signal_%ld.jpg\" width=%d height=%d><br><br>\n", (int) this_ap_signal.id, picwidth, picheight);
      } else if(plot_type == 2) {
        sprintf(waterfall_mv, "mv plots/waterfall.jpg plots/timeseries_ap_signal_%d.jpg", this_ap_signal.id);
        fprintf(html_file, "<img src=\"plots/timeseries_ap_signal_%ld.jpg\" width=%d height=%d><br><br>\n", (int) this_ap_signal.id, picwidth, picheight);
      } else if(plot_type == 3) {
        sprintf(waterfall_mv, "mv plots/waterfall.jpg plots/lcgammplot_ap_signal_%d.jpg", this_ap_signal.id);
        fprintf(html_file, "<img src=\"plots/lcgammplot_ap_signal_%ld.jpg\" width=%d height=%d><br><br>\n", (int) this_ap_signal.id, picwidth, picheight);
      }
      retval = system(waterfall_mv);
      if(retval) {
        printf("In query_to_html : mv failed.<br>\n");
        exit(-1);
      }
    }
  
  }
  
}

fprintf(html_file, "In query_to_html: %d rows found.<br><br>\n", num);
fprintf(html_file, "<body></html>\n");
fclose(html_file);

// Print a link to the html file
printf("<html>\n<head>\n");
printf("<meta http-equiv=\"REFRESH\" content=\"0;url=http://setiathome.ssl.berkeley.edu/~boincadm/%s\"", html_filename);
printf("</head>\n");

}
