// Crude initial attempt at a distributed version of
// matrix-vector product: 
// This is a client that connects to two matrix servers
// holding the same matrix and uses their matrix block_product
// functions.  The call of the first server's block_product 
// function computes the top half of a matrix-vector product
// and the call on the second server does the second
// half.  In this program these calls are not done in 
// parallel.  Experimenting with that is the next step!
//
#pragma warning (disable : 4786)
#include <iostream.h>
#include <vector>
using namespace std;

#include "matrix.h"
#include "namebind.cpp"

int main( int argc, char *argv[] )
{
  // ORB initialization
  CORBA::ORB_var orb = CORBA::ORB_init(argc, argv, "omniORB2");
  CORBA::BOA_var boa = orb->BOA_init(argc, argv, "omniORB2_BOA");

  vector<Matrix_var> client;
  int j;
  for (j = 1; j <= 2; ++j) {
    cout << "j = " << j << endl;
    try {
      CORBA::Object_var obj = getObjectReference(orb, "test", argv[j]);
      cout << "got here" << endl;
      client.push_back(Matrix::_narrow(obj));
      if (CORBA::is_nil(client[j-1])) {
	cerr << "Cannot invoke on a nil object reference.\n" << endl;
	return 1;
      }
      assert(!CORBA::is_nil(client[j - 1]));
    }
    catch(CORBA::COMM_FAILURE& ex) {
      cerr << "Caught system exception COMM_FAILURE, unable to contact the "
	   << "object." << endl;
      return 1;
    }
    catch(omniORB::fatalException& ex) {
      cerr << "Caught omniORB2 fatalException. This indicates a bug is caught "
	   << "within omniORB2.\nPlease send a bug report.\n"
	   << "The exception was thrown in file: " << ex.file() << "\n"
	   << "                            line: " << ex.line() << "\n"
	   << "The error message is: " << ex.errmsg() << endl;
      return 1;
    }
    catch(...) {
      cerr << "Caught a system exception." << endl;
    }
  }
  const int N = 10;
  Column c;
  c.length(N);
  // Create a column of all 3's.
  for (int i = 0; i < N; ++i) 
    c[i] = 3;
  
  cout << "Computing the matrix-vector product..." << endl;
  vector<Column*> result(2);
  result[0] = client[0]->block_product(0, N/2, c);
  result[1] = client[1]->block_product(N/2, N, c);
  
  // Output the whole result, first half from result[0] followed by 
  // second half from result[1]:
  cout << "The result: " << endl;
  for (j = 0; j < 2; ++j) {
    for (int k = 0; k < result[j]->length(); ++k)
      cout << (*result[j])[k] << " ";
  }
  cout << endl;
  return 0;
}

