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

Copyright (C) 2007.

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 <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

using namespace scl;
using namespace std;

int main(int argc, char** argp, char** envp)
{
  char** ptr = argp;
  char* arg = *ptr++;
  string progname;
  while(*arg) progname.push_back(*arg++);

  if (argc != 5) {
    warn(" ");
    warn("Usage :  " + progname + " prefix procnum nfile stride"); 
    warn(" ");
    warn("Where :  prefix is as specified in control.dat");
    warn("         cpu's are presumed to be numbered 0,1,2,...,procnum");
    warn("         nfile is as specified in the paramfile");
    warn("         stride is chosen by the user");
    warn("         effective stride is the parmfile stride times user stride");
    warn(" ");
    warn("Example: "+progname+" sv 15 9 10");
    warn(" ");
    warn("         for a run with last output filename \"sv.stats.015.009\"");
    error(" ");
  }

  arg = *ptr++;
  string prefix;
  while(*arg) prefix.push_back(*arg++);

  INTEGER processors = atoi(*ptr++);
  INTEGER nfile = atoi(*ptr++);
  INTEGER stride = atoi(*ptr++);

  cout << "prefix = " << prefix << '\n';
  cout << "procnum = " << processors << '\n';
  cout << "nfile = " << nfile << '\n';
  cout << "stride = " << stride << '\n';

  if (processors > 999 || nfile > 999) {
    error("Error, "+progname+" nfile or processors too big");
  }

  struct stat  statbuf;
  struct stat* statptr = &statbuf;

  string dirname="concatenated_files";

  if (stat(dirname.c_str(),statptr) == -1) {
    mode_t permissions=S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
    if (mkdir(dirname.c_str(),permissions) != 0) {
      error("Error, "+progname+", cannot mkdir "+dirname);
    }
  }
  else if ((statptr->st_mode & S_IFMT) != S_IFDIR) {
    error("Error, "+progname+", "+dirname+" exists but is not a directory");
  }

  dirname += "/";

  vector<string> filetypes;
  filetypes.push_back(".rho");
  filetypes.push_back(".pi");
  filetypes.push_back(".stats");

  typedef vector<string>::const_iterator vscitr;

  for (INTEGER n=1; n<=processors; ++n) {
    for (vscitr t=filetypes.begin(); t<filetypes.end(); ++t) {
      realmat out;
      for (INTEGER f=0; f<=nfile; ++f) {
  
        stringstream extension;
        stringstream newextension;
  
        if (n < 10) {
          extension << ".00" << n;
          newextension << ".00" << n << ".dat";
        }
        else if (n < 100) {
          extension << ".0" << n;
          newextension << ".0" << n << ".dat";
        }
        else {
          extension << "." << n;
          newextension << "." << n << ".dat";
        }
        
        if (f < 10) {
          extension << ".00" << f;
        }
	else if (f < 100) {
	  extension << ".0" << f;
	}
        else {
          extension << "." << f;
        }
      
        string filetype = *t;
  
        string filename = prefix + filetype + extension.str();
  
        realmat in;
        realmat outf;
  
        if (!vecread(filename.c_str(),in)) {
          error("Error, "+progname+" cannot read "+filename);
        }
  
        INTEGER newcol = in.get_cols()/stride;
        if (in.get_cols() % stride != 0) ++newcol;
  
        outf.resize(in.get_rows(),newcol);
        INTEGER count = 0; 
        for (INTEGER j=1; j<=in.get_cols(); j+=stride) {
          ++count;
          for (INTEGER i=1; i<=in.get_rows(); ++i) {
  	  outf(i,count) = in(i,j);
          }
        }

        if (count != newcol) {
	  error("Error, "+progname+" this should not happen");
        }
  
        if (f == 0) {
          out = outf;
        }
        else {
          out = cbind(out,outf);
        }
  
        if (f == nfile) {
          filename = dirname + prefix + filetype + newextension.str();
          cout << filename << '\n';
          if (!vecwrite(filename.c_str(),out)) {
            error("Error, "+progname+" cannot write "+filename);
          }
        }
  
      }
    }
  }

  return 0;
}
