// ----------------------------------------------------------------------------
//
// Copyright (C) Columbia University, 1994. All Rights Reserved.
// Sameer A. Nene, Shree K. Nayar, Hiroshi Murase
//
// See file LICENSE for details of software license agreement.
//
// ----------------------------------------------------------------------------
//
// project.C
//
// Author:               Sameer Nene
// Date:                 06/07/94
// Version:              1.0.0
// Modification History:
//
// Classes:
//
// Notes:
//   This command is used for projecting vectors to a supplied eigen space.
//   See the man page for more details.
//   
// ----------------------------------------------------------------------------

#include <iostream.h>
#include <stdlib.h>
#include <string.h>
#include "errorscope.h"
#include "vector.h"
#include "dataset.h"
#include "parser.h"
#include "fileiter.h"
#include "ioutil.h"
#include "reporter.h"
#include "stringary.h"

int main(int argc, char **argv)
{
  int i, k, l, m, n;
  char buf[1024], *p;
  CommandParser cp(argc, argv, "a:c:e:n:ACD:V");
  ErrorScope::Error error;
  Vector v, vavg;
  
  if((error = cp.error()) != ErrorScope::OK) {
    cerr << error << endl << "Exiting" << endl;
    exit(1);
  }

  if(cp.getVerboseFlag() != 0)
    cerr << "Copyright \xA9 Columbia University, 1994. All Rights Reserved." << endl << "Sameer Nene, Shree Nayar, Hiroshi Murase" << endl << endl << "Reading Eigen Vectors" << endl;
  
  VectAry va;
  const char *evc = cp.getEigenVectorFileName();
  if((error = IOUtil::get(&va, evc)) != ErrorScope::OK) {
    cerr << error << ": " << evc << endl << "Exiting" << endl;
    exit(1);
  }

  if((k = cp.getNumEigenVectors()) == 0)
    k = va.getSize();
  else if(k > va.getSize())
    cerr << endl << "Number of Eigen Vectors present less than requested. Defaulting to " << (k = va.getSize()) << endl;

  Vector v2(k);

  if(cp.getVerboseFlag() != 0)
    cerr << endl << "Projecting Images to Eigen Space" << endl;

  if(cp.getAverageFlag() != 0)
    if((error = IOUtil::get(&vavg, cp.getAverageVectorFileName())) !=
       ErrorScope::OK) {
      cerr << error << ": " << cp.getAverageVectorFileName() << endl << "Exiting" << endl;
      exit(1);
    }

  const StringAry &sa = cp.getObjectList();
  FileListAry fa(cp.getObjectDirectory(), sa, "vec");
  if((error = fa.error()) != ErrorScope::OK) {
    cerr << error << endl << "Exiting" << endl;
    exit(1);
  }

  if(cp.getCombineFlag()) {
    for(l = 0, m = fa.getSize(), i = 0; l < m; i += fa[l++].getSize());
    DataSet ds(1, i);
    DataSetIter dsit(ds);
    ds.setSize(0, i);

    for(l = 0; l < m; ++l)
      for(FileListIter it(fa[l]); it; ++it, ++dsit) {
	if(cp.getVerboseFlag() != 0)
	  Reporter::display_status();
	
	if((error = IOUtil::get(&v, it())) != ErrorScope::OK) {
	  cerr << error << ": " << it() << endl << "Exiting" << endl;
	  exit(1);
	}

	if(cp.getAverageFlag() != 0)
	  v -= vavg;
	
	i = 0;
	for(VectAryIter it(va); i < k; ++it, ++i)
	  v2.element(i, v * it());
	dsit() = v2;
      }

    strcat(strcpy(buf, cp.getCombineName()), ".prj");

    if((error = IOUtil::put(ds, buf)) != ErrorScope::OK) {
      cerr << error << ": " << buf << endl << "Exiting" << endl;      
      exit(1);
    }
  }
  else {
    for(l = 0, m = fa.getSize(); l < m; ++l) {
      DataSet ds(n = fa[l].getNumParam(), fa[l].getSize());
      for(i = 0; i < n; ++i)
	ds.setSize(i, fa[l].getSize(i));
      
      DataSetIter dsit(ds);
      for(FileListIter it(fa[l]); it; ++it, ++dsit) {
	if(cp.getVerboseFlag() != 0)
	  Reporter::display_status();
	
	if((error = IOUtil::get(&v, it())) != ErrorScope::OK) {
	  cerr << error << ": " << it() << endl << "Exiting" << endl;
	  exit(1);
	}

	if(cp.getAverageFlag() != 0) 
	  v -= vavg;
	
	i = 0;
	for(VectAryIter it(va); i < k; ++it, ++i)
	  v2.element(i, v * it());
	dsit() = v2;
      }
      
      if((p = strchr(strcat(strcat(strcpy(buf, sa[l]), "__"), evc), '.')) != 0)
	*p = '\0';
      if((error = IOUtil::put(ds, strcat(buf, ".prj"))) != ErrorScope::OK) {
	cerr << error << ": " << buf << endl << "Exiting" << endl;      
	exit(1);
      }
    }
  }

  if(cp.getVerboseFlag() != 0)
    cerr << endl << endl << "Done" << endl;

  return 0;
}
