
#ifndef AP_STATE_H
#define AP_STATE_H

#include "mtrand.h"

namespace Astropulse {

class state_signal {
    public:
        sqlint8_t  id;
        // OLD: db_reference<result,sqlint8_t> resultid;
        // NEW: long long resultid;
        long  fft_num;
        long  peak_bin;
        double  peak_power;
        long  scale;
        long  dm;
        double  period;
	long ffa_scale;
	double num_std_devs;
        double  ra;
        double  decl;
        double  time;
        long  rfi_found;
        long  reserved;
        long  time_series_len;
        // sqlblob<unsigned char>  time_series;
        unsigned char time_series[MAXLENGTH_OF_TS];

        state_signal() {}
        state_signal(const ap_signal &sig) : 
            id(sig.id),
            fft_num(sig.fft_num), peak_bin(sig.peak_bin),
            peak_power(sig.peak_power), scale(sig.scale), dm(sig.dm),
            period(sig.period), ffa_scale(sig.ffa_scale), num_std_devs(sig.num_std_devs),
            ra(sig.ra), decl(sig.decl), time(sig.time),
            rfi_found(sig.rfi_found), reserved(sig.reserved),
            time_series_len(sig.time_series_len) {

            // TEMP - let's see if this works.
            /* memcpy(time_series, &(sig.time_series[0]), sig.time_series.size()); */
	    if(sig.time_series.size() > MAXLENGTH_OF_TS) {
	      printf("In state_signal::state_signal(): ap_signal time_series is too long.\n");
	      fprintf(stderr, "In state_signal::state_signal(): ap_signal time_series is too long.\n");
	    }
	    std::copy(sig.time_series.begin(), sig.time_series.end(),
				 time_series);
        }
        operator ap_signal() {
            ap_signal sig;
            sig.id = id;
            // sig.resultid = resultid;
            sig.fft_num = fft_num;
            sig.peak_bin = peak_bin;
            sig.peak_power = peak_power;
            sig.scale = scale;
            sig.dm = dm;
            sig.period = period;
	    sig.ffa_scale = ffa_scale;
	    sig.num_std_devs = num_std_devs;
            sig.ra = ra;
            sig.decl = decl;
            sig.time = time;
            sig.rfi_found = rfi_found;
            sig.reserved = reserved;
            sig.time_series_len = time_series_len;
            sig.time_series = sqlblob<unsigned char>(time_series, 64, _x_hex);
            return sig;
        }
};

const int NUM_SAMPLES = 32L * 1024L * 1024L;

// Structure which includes everything that might be in a wu header.  Also
// contains info for state file.
struct state_t {
  char recvname[64];      // receiver name
  unsigned char wuname[64];        // workunit name
  int datasize;           // Size of raw data in bytes
  int dm_low;             // Lowest dm to calculate
  int dm_hi;              // Highest dm
  int dm_chunk_large;     // dm resolution for folding - also dm table size
  int dm_chunk_small;	  // second dm resolution
  int fft_len;            // fft length >= 2*dm_hi
  float high_pass;       // Hertz.  See ap_science.cpp, high_pass_filter()
  float ffa_threshold;    // lcgf threshold, should be a negative number
  int max_coadd;          // max level to collapse down to ( >= log(dm_chunk) )
  int fold_buf_size_short;      // size of array to fold
  int fold_buf_size_long;
  int remove_radar;		// 0: don't remove radar, 1: do remove radar
  int fold_buf_bytes_short; // bytes of date represented in short fold buffer
  int fold_level_large;         // should be log2(dm_chunk)
  int fold_level_small;        // should be log2(dm_chunk_small)
  double thresh[MAX_COADD];// array of thresholds (max_collapse total)
  double ra0;             // RA at start of wu, in hours
  double ra1;             // RA at end of wu
  double dec0;            // Dec at start of wu, in degrees
  double dec1;            // Dec at end of wu
  double jd0;             // JD at start
  double jd1;             // JD at end
  int data_chunk_now;     // Current location being worked on
  int dm_chunk_large_now;       // Current dm chunk
  int dm_chunk_small_now; 
  int dm_now;             // Current dm within chunk
  int dm_sign;            // positive (+1) or negative (-1) dispersion
  int num_sub_buffers;    // for ffa number of sub buffers
  int sub_buffer;         // for ffa, current sub buffer
  // using increased precision for freq and min_freq
  double freq;             // for ffa, = number of periods
  double min_freq;         // for ffa, minimum freq to consider
  int nfb;				  // for ffa build threshold table
  int fold_buf_loc_long_pos; // location to write in fold buffer
  int fold_buf_loc_long_neg;
  int fold_buf_loc_short_pos;
  int fold_buf_loc_short_neg;
  double frac_done;       // fraction of wu completed so far
  double pulse_jd;        // dummy to calculate the julian date of pulse
  int result_count_single;       // number of single pulse results found so far
  int result_count_rep;       // number of repeating pulse results found so far
  state_signal best[MAX_COADD];
  enum code_segment_name code_segment;
  MtRand mtr;  // state of the random number generator
  MtRand mtr_new;
  long numSamplesBlanked;
  long numSamplesBlankedNew;
  long lastDataChunkBlanked;
  long lastDataChunkBlankedNew;
  // int idum;  // seed for random number generator
  // int idum_new;  // seed that will be used in next randomization

  state_t();
  void compute_fraction_done(double l);
  void print();
};

}
#endif
