//------------------------------------------------------------
// $Id: main.cc,v 1.5.2.1 2000/06/14 17:46:35 yamauchi Exp $
//------------------------------------------------------------
//	mpi2 main
//	1996/7/5
//	Copyright (C) 1996--1998  YAMAUCHI Hitoshi 山内 斉
//------------------------------------------------------------
#include <stdio.h>
#include <iostream.h>
#include <iomanip.h>
#include <new.h>

#define THIS_IS_GLOBAL_DEFINE_FILE
#include "StandAloneModeObjects.h"
#include "adjdir.h"
#include "Option.h"
#include "FileInfo.h"
#include "PE.h"
#include "config.h"
#include "host.h"
#include "mpi2communication.h"
#include "stopwatch.h"
#include "ElapsedTimer.h"
#include "version.h"
#include "ProfileMon.h"

//------------------------------------------------------------
// 使用法
//------------------------------------------------------------
void usage(const char * const com_name)
{
    // 誰かが usage を出力して終了 (ここでは rank == 0 が usage & exit を行う)
    if(SysStat::getInstance()->getMyRank() == 0)
    {
	cerr <<"Usage: " << com_name << " [-dhvsS]" << endl;
	cerr <<"\t[--conf] configfile\n";
	cerr <<"\t[--spc] spcfile [--sys] sysinfofile [--view] viewfile\n";
	cerr <<"\t[--mat] materialfile [--geo] geometryfile\n";
	cerr <<"\t[--vinl] volume infile list file\n";
	cerr <<"\t[[--rado] radiosityresout] [--save[ppm|gfb]] imagesavefile\n"
	     << endl;
	cerr << "  Options:\n";
	cerr << "\t-d\tDebug mode\n";
	cerr << "\t-h\tPrint this message\n";
	cerr << "\t-v\tVerbose mode\n";
	cerr << "\t-s\tShow read data\n";
	cerr << "\t-S\tShow number of objects in subspaces\n";
	cerr << "\t--[conf|sys|view|spc|mat|geo|vinl] identify read file\n";
	cerr << "\t  \tconf ... configuration (all config) file\n";
	cerr << "\t  \tspc  ... space (definespace etc.) file\n";
	cerr << "\t  \tsys  ... system configuration file\n";
	cerr << "\t  \tview ... view file (viewpoint etc.)\n";
	cerr << "\t  \tmat  ... material information file\n";
	cerr << "\t  \tgeo  ... geometry information file. '(stdin)' is OK.\n";
	cerr << "\t  \tvinl ... volume data infile list file\n";
	cerr << "\t  contents of conf file is override with other options.\n";
	cerr << "\t--[rado|save[ppm|gfb]] identify output filename"<< endl;
	cerr << "\t  \trado    ... radiosity result as mpi2 patch(basename)\n";
	cerr << "\t  \tsaveppm ... rendering result as ppm format\n";
	cerr << "\t  \tsavegfb ... rendering result as global frame "
	    "buffer(gfb) format\n";
	cerr << "\t  \t            refer to mpi2.GFBraw.doc\n";
	cerr << "\t--rado is only available in stand alone mode"<<endl;
	cerr << "\t\t(C) YAMAUCHI Hitoshi yamauchi@archi.is.tohoku.ac.jp\n";
	cerr << "(Mpi)2 for 1PE version (not parallel processing)";
	cerr << endl;
	cerr << MPI2_VERSION 					<< endl;
    }
    commMpi2_exit(1);	
}

//------------------------------------------------------------
// main
//------------------------------------------------------------
// work of host computer 
static void do_host(int hostrank)
{
    GpHost->init(hostrank);

    outPERawTime("Host: start read and deliver data.");
    ElapsedTimerClass etimer; 	
    etimer.start();
    GpHost->readAndDeliverAllData();
    etimer.stop();		
    outPERawTime("Host: done read and deliver data.");
    outPEEtime("Host: elapsed time of read and deliver data.", etimer);

    // GpHost->doRadiosity();	// radiosity を始めるというコマンド送信
    // GpHost->doPrepareShading();// shading のための情報交換や計算
    // GpHost->doRayTracing();	// ray tracing を始めるというコマンド送信
}    

// work of Processing Element
static void init_PE(void)
{
    // GpPE->setID(IntVec3(0, 0, 0));
}

//------------------------------
// do PE
//------------------------------
static void do_PE(void)
{
    // GpPE->initBeforeRendeirng();
    if(Option::getInstance()->getShowDataMode() == YES)
    {
	GpPE->printSysInfo(NORMALHEAD);
	GpPE->printMaterials(NORMALHEAD);
	GpPE->printObjects(NORMALHEAD);
    }
    if(Option::getInstance()->getShowNumobjInSpace() == YES)
    {
	GpPE->printObjInSpcMap(NORMALHEAD);
    }
    // 本来は、host の送信(material, object)が終了したら command を待
    // つ。したがってここにはコマンドの dispatch routine が入る
    // host からの command によってなにをするか決めるようにするが、
    // select system call のようなことも MPI では可能のようである。
    // (MPI_Probe) 
    // その実装は今後決める。ある atomic な部分ではつっぱしる、つまり
    // 多重入力はしない方向で実装すれば良いと思う。 

    //------------------------------------------------------------
    // radiosity stage 
    //------------------------------------------------------------
    outPERawTime("start radiosity stage.");
    StopWatchClass watch;    	watch.start();    
    ElapsedTimerClass etimer; 	etimer.start();
    GpPE->doRadiosity();
    etimer.stop();		outPEEtime(": radiosity stage.", etimer);
    watch.stop(); 		outPEwatch("watch radiosity", watch);
    outPERawTime("done radiosity stage.");

    if(FileInfo::getInstance()->isRadioStageResultOut() == YES)
    {
	GpPE->outRadiosityMpi2Data(FileInfo::getInstance()->
				   getRadioStageOutFileName(),  YES);
    }
    GpPE->printStatInfo("Radiosity"); // 統計情報の出力

    //------------------------------------------------------------
    // prepare shading stage 
    //------------------------------------------------------------
    outPERawTime("start prepare shading.");
    watch.start();
    etimer.start();
    GpPE->doPrepareShading();
    etimer.stop();		outPEEtime(": prepare shading stage.", etimer);
    watch.stop(); 		outPEwatch("watch prepare shading.", watch);
    outPERawTime("done prepare shading.");

    //------------------------------------------------------------
    // ray-tracing stage 
    //------------------------------------------------------------
    outPERawTime("start ray-tracing stage.");
    watch.start();
    etimer.start();
    GpPE->doRayTracing();
    etimer.stop();		outPEEtime(": ray-tracing stage.", etimer);
    watch.stop();  		outPEwatch("watch ray-tracing.", watch);
    outPERawTime("done ray-tracing stage.");

    GpPE->printStatInfo("RayTracing"); // 統計情報の出力
#ifdef COUNT_SKIP_SPACE
    cout << NORMALHEAD << " PE:: skip/traverse spaces of rays " << 
    	GpPE->getSkipSpcOfRays() << "/" << GpPE->getTravSpcOfRays() << endl;
#endif
}

// exit new (gcc では default があるが、xlC, mpCC には無いようだ)
// if((somethingPtr = new something) == NULL) の時 call される
void newExit(void)
{
    cerr << "Virtual memory exceeded in mpi2 new. exit." << endl;
    commMpi2_exit(1);
}


// to get object size
//#include "triangleObject.h"
//#include "sphereObject.h"

// stand alone
int main(int argc, char *argv[]) 
{
    // cout << "objsize = " << sizeof(triangleObjectClass) << endl;
    // cout << "spheresize = " << sizeof(sphereObjectClass) << endl;
    
    set_new_handler(newExit);
    commMpi2_Init(&argc, &argv);

    // get Option and FileInfo
    FileInfo commandLineFinfo;    
    getOption(argc, argv, &commandLineFinfo);
    setFileInfo(commandLineFinfo);
    SysStat::getInstance()->setHostRank(1); // stand alone

    // PrifileMonitor init
    ProfileMon::getInstance()->init(SysStat::getInstance()->getMyRank(), 
				    FileInfo::getInstance()->
				    getTraceFileBaseName());

    GpPE   = new PEClass();		// stand alone  
    GpHost = new hostComputerClass();	// stand alone  

    cout << "//-----------------------------------------------------" << endl;
    cout << "// Stand Alone mode can not skip the radiosity stage.  " << endl;;
    cout << "// if you want to skip the radiosity stage. Please set " << endl;
    cout << "// a minRadiationEnergy Huge val(like 1e20) in a view  " << endl;
    cout << "// file data. and never off Rendering  = Radiosity     " << endl;
    cout << "// in a sysinfo file.    YAMAUCHI Hitoshi              " << endl;
    cout << "//-----------------------------------------------------" << endl;

    init_PE();
    do_host(1);
    do_PE();

    commMpi2_Finalize();
    GpHost->outResult();	// 全員終了したら結果出力(あるいは 
				// ray-tracing では常に出力)
}
