/*-----------------------------------------------------------------------------

Copyright (C) 2020.

A. Ronald Gallant
Post Office Box 659
Chapel Hill NC 27514-0659
USA   

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

-----------------------------------------------------------------------------*/

#include "libscl.h"
#include "npbusr.h"
#include "npb.h"
#include "snp_npb_mod.h"

using namespace scl;
using namespace std;
using namespace npb;

const INTEGER start   =     0;
const INTEGER stop    =    19;
const INTEGER stride  =    50;
    
const INTEGER drop     =   14;
const INTEGER big_down =  403;
const INTEGER big_up   = 2261;

const INTEGER sig_nrow = 3;
const INTEGER sig_ncol = 2250;

int main(int argc, char** argp, char** envp)
{

  istream* ctrl_ptr;
  if (argc == 2) {
    ctrl_ptr = new(nothrow) ifstream(argp[1]);
    string msg = "Error, npb, " + string(argp[1]) + " open failed";
    if( (ctrl_ptr == 0) || (!*ctrl_ptr) ) error(msg);
  }
  else {
    ctrl_ptr = new(nothrow) ifstream("control.dat");
    string msg = "Error, npb, control.dat open failed";
    if( (ctrl_ptr == 0) || (!*ctrl_ptr) ) error(msg);
  }
  istream& ctrl = *ctrl_ptr;

  string parmfile;
  string prefix;

  ifstream fin;
  ofstream fout;
  string filename;
  
 
  while(ctrl >> parmfile >> prefix) {  // Begin ctrl loop

    filename = prefix + ".detail.dat";

    ofstream detail_ofs(filename.c_str());
    if (!detail_ofs) error("Error, npb, detail.dat open failed");
    ostream& detail = detail_ofs;

    string pfline;

    vector<string> pfvec;
    ifstream pf_ifs(parmfile.c_str());
    if (!pf_ifs) error("Error, npb, cannot open parmfile " + parmfile);
    while (getline(pf_ifs, pfline)) pfvec.push_back(pfline);

    npbpfile pf;

    if(!pf.set_pfile(pfvec,detail)) {
       detail.flush();
       error("Error, npb, cannot read npb parmfile");
    }

    estblock est_blk = pf.get_estblock();
    datblock dat_blk = pf.get_datblock();
    modblock mod_blk = pf.get_modblock();

    realmat data; 
    if (!dat_blk.read_data(data)) {
      error("Error, npbparm, cannot read data, dsn = " + dat_blk.dsn);
    }

    if (est_blk.print) {
      detail << starbox("/First 12 observations//");
      detail << data("",seq(1,12));
      detail << starbox("/Last 12 observations//");
      detail << data("",seq(dat_blk.n-11, dat_blk.n));
      detail.flush();
    }

    if (est_blk.print) {
      detail << starbox("/snp_npb_mod constructor now controls print//");
      detail << '\n';
      detail.flush();
    }

    snp_npb_mod snpmod(&data, pf.get_snp_pfile(), pf.get_mod_alvec(), detail);

    {
      realmat snp_raw_data = snpmod.get_raw_data();
      if (data.size() == snp_raw_data.size()) {
        for (INTEGER i=1; i<=data.size(); ++i) {
          REAL relerr = fabs(data[i]-snp_raw_data[i])/(fabs(data[i]+1.0e-5));
          if (relerr > 1.0e-3) {
            error("Error, data read by npb not the same as read by snpmod");
          }
        }
      }
      else {
        error("Error, data read by npb not the same as read by snpmod");
      }
    }

    if (est_blk.print) {
      detail << starbox("/end of snp_npb_mod constructor print control//");
    }

    if (est_blk.print) {
      detail << starbox("/npbusr construction begins//");
      detail << '\n';
      detail.flush();
    }

    realmat parms = pf.get_parms();
    INTEGER l_parms = parms.size();

    realmat snp_parms;
    snpmod.get_parm(snp_parms);

    INTEGER l_snp_parms = snp_parms.size();
    INTEGER l_cmf_parms = l_parms - l_snp_parms;

    if (est_blk.print) {
      detail << '\n';
      detail << '\t' << "l_parms = " << l_parms << '\n';
      detail << '\t' << "l_snp_parms = " << l_snp_parms << '\n';
      detail << '\t' << "l_cmf_parms = " << l_cmf_parms << '\n';
      detail << '\n';
      detail.flush();
    }

    realmat cmf_parms;
    for (INTEGER i=l_snp_parms+1; i<=l_parms; ++i) {
      cmf_parms.push_back(parms[i]);
    }

    for (INTEGER i=1; i<=l_snp_parms; ++i) {
      snp_parms[i] = parms[i];
    }

cerr << "Got to here"  << '\n';
    snpmod.set_parm(snp_parms);

    filename = "parm_chain.in3";
    snpmod.write_parmfile(filename.c_str());

    system("snp");

    filename = "parm_chain.sig";
    realmat sig;
    vecread(filename.c_str(),sig,sig_nrow,sig_ncol);

    if (est_blk.print) {
    
      detail << starbox("/Parameter Settings//") << snp_parms << '\n';

      detail << "start = " << start << '\n';
      detail << "stop  = " << stop  << '\n';
      detail << "drop  = " << drop  << '\n';
      detail << "big_down = " << big_down << '\n';
      detail << "big_up   = " << big_up    << '\n';
      detail << "big_down and big_up for k = 1" << '\n';
      detail << sig("",big_down-drop) << '\n';
      detail << sig("",big_up-drop) << '\n';
      detail << '\n';
      detail.flush();
    }

    filename = "big_down_SP500.sig";
    ofstream fout_big_down_SP500(filename.c_str());
    if (!fout_big_down_SP500) error("Error, cannot open " + filename);

    filename = "big_down_SP_NAS.sig";
    ofstream fout_big_down_SP_NAS(filename.c_str());
    if (!fout_big_down_SP_NAS) error("Error, cannot open " + filename);

    filename = "big_down_NASDAQ.sig";
    ofstream fout_big_down_NASDAQ(filename.c_str());
    if (!fout_big_down_NASDAQ) error("Error, cannot open " + filename);

    filename = "big_up_SP500.sig";
    ofstream fout_big_up_SP500(filename.c_str());
    if (!fout_big_up_SP500) error("Error, cannot open " + filename);

    filename = "big_up_SP_NAS.sig";
    ofstream fout_big_up_SP_NAS(filename.c_str());
    if (!fout_big_up_SP_NAS) error("Error, cannot open " + filename);

    filename = "big_up_NASDAQ.sig";
    ofstream fout_big_up_NASDAQ(filename.c_str());
    if (!fout_big_up_NASDAQ) error("Error, cannot open " + filename);

    for (INTEGER k=start; k<=stop; ++k) {

      filename 
         = "/home/arg/r/npb/sdf_npb_sv/combined/" + prefix + ".parms_chain." 
            + fmt('d',3,k)('0') + ".dat";

      realmat parms_chain;
      vecread(filename.c_str(),parms_chain);

      for (INTEGER j=1; j<=parms_chain.ncol(); j += stride) {

        for (INTEGER i=1; i<=l_snp_parms; ++i) {
          snp_parms[i] = parms_chain(i,j);
        }

        snpmod.set_parm(snp_parms);

        filename = "parm_chain.in3";
        snpmod.write_parmfile(filename.c_str());

        system("snp");

        filename = "parm_chain.sig";
        vecread(filename.c_str(),sig,sig_nrow,sig_ncol);

        fout_big_down_SP500   << fmt('f',20,8,sig(1,big_down-drop)) << '\n';
        fout_big_down_SP_NAS  << fmt('f',20,8,sig(2,big_down-drop)) << '\n';
        fout_big_down_NASDAQ  << fmt('f',20,8,sig(3,big_down-drop)) << '\n';
        fout_big_up_SP500     << fmt('f',20,8,sig(1,big_up-drop)) << '\n';
        fout_big_up_SP_NAS    << fmt('f',20,8,sig(2,big_down-drop)) << '\n';
        fout_big_up_NASDAQ    << fmt('f',20,8,sig(3,big_up-drop)) << '\n';
      }

    }  // End ctrl loop

  delete ctrl_ptr;
  return 0;
  }
}
