// main.cpp

// includes

#include <cstdio>
#include <cstdlib>

#include "attack.h"
#include "book.h"
#include "hash.h"
#include "move_do.h"
#include "option.h"
#include "pawn.h"
#include "piece.h"
#include "protocol.h"
#include "random.h"
#include "square.h"
#include "trans.h"
#include "util.h"
#include "value.h"
#include "vector.h"

// kh 10.04.07 start Thomas Gaksch
#include "probe.h"

static char * egbb_path = "c:/egbb/";

// kh 30.05.08 Thomas Gaksch 14b5c
//static uint32 egbb_cache_size = 32; 
static uint32 egbb_cache_size = 16; 

// kh 10.04.07 end Thomas Gaksch

#if defined(_WIN32) || defined(_WIN64)

  #include <windows.h>

#else // assume POSIX
//#  include <sys/resource.h>
//#  include <sys/time.h>
//#  include <sys/types.h>

  #include <unistd.h>

#endif

#if defined(_WIN32) || defined(_WIN64)

  extern "C"
  {
    #include "MPIWrapper.h"
  }

#else // assume POSIX

  extern "C"
  {
    #include "MPIWrapper.h"
  }

#endif

#include "CommPrinter.h"
#include "YBWCManager.h"

// functions

// main()
int main(int argc, char* argv[]) 
{
  int           nResult;
  int           nExitResult;

#if defined(_WIN32) || defined(_WIN64)

// kh 04.08.06 enables memory leak detection
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

#endif

  nExitResult = EXIT_FAILURE;

// init

/*
  printf("initializing environment...\n");
  fflush(stdout);
*/


#if defined(_WIN32) || defined(_WIN64)

//Sleep(30000); // kh 06.09.06 used for debug purposes

#else // assume POSIX

//sleep(30);    // kh 02.10.06 used for debug purposes

#endif

// kh 20.03.08 do this early to be able to access the actual default uci options in YBWCManager_Init(...
// for YBWCManager_SetMachineInfo(...
  option_init(); 

  nResult = MPIWrapper_Init(MPIWrapper_Instance(), &argc, &argv);
  if(nResult == MPI_SUCCESS)
  {
    nResult = YBWCManager_Init(YBWCManager_Instance(), &argc, &argv); 
    if(nResult == MPI_SUCCESS)
    {
      if(YBWCManager_Instance()->bRootMaster)
      {
        YBWCManager_Printf(YBWCManager_Instance(), 
                           "root environment for <%s> successfully initialized\n",
                           YBWCManager_Instance()->sProcessorName);
      } // if(YBWCManager_Instance()->bRootMaster)
      else
      {
        YBWCManager_Printf(YBWCManager_Instance(), 
                           "non root environment for <%s> successfully initialized\n",
                           YBWCManager_Instance()->sProcessorName);
      } // !if(YBWCManager_Instance()->bRootMaster)

      if(YBWCManager_Instance()->pCommandLine->bExitRequest)
      {
        // kh 28.07.06 e.g. --help or --version are found as command line arguments
      }
      else
      {
        util_init();
        my_random_init(); // for opening book

        if(YBWCManager_Instance()->bRootMaster)
        {
          printf(PROGRAM_NAME " " PROGRAM_VERSION " " PROGRAM_DETAILS "\n");
          fflush(stdout);

// kh 04.08.06 special suppress of log to stdout once
          YBWCManager_SaveLogSettings(YBWCManager_Instance(), LogSettings_Instance());

          YBWCManager_Instance()->pFruitConfiguration->bLogToStdout = FALSE;
          YBWCManager_Printf(YBWCManager_Instance(), 
                             PROGRAM_NAME " (root master) " PROGRAM_VERSION " " PROGRAM_DETAILS "\n");

          YBWCManager_LoadLogSettings(YBWCManager_Instance(), LogSettings_Instance());
        } // if(YBWCManager_Instance()->bRootMaster)
        else
        {
          YBWCManager_Printf(YBWCManager_Instance(), 
                             PROGRAM_NAME " (non root master) " PROGRAM_VERSION " " PROGRAM_DETAILS "\n");
        } // !if(YBWCManager_Instance()->bRootMaster)

        // early initialisation (the rest is done after UCI options are parsed in protocol.cpp)

// kh 20.03.08 moved up a few lines (see above)
/*
        option_init();
        FruitConfiguration_UpdateOptions(YBWCManager_Instance()->pFruitConfiguration);
*/

        if(YBWCManager_Instance()->bRootMaster) // kh 12.02.08 root master only for the moment
        {

/*
// kh 13.02.08 special enable of log to common file once
          YBWCManager_SaveLogSettings(YBWCManager_Instance(), LogSettings_Instance());

          YBWCManager_Instance()->pFruitConfiguration->bLogToCommonFile = TRUE;

          FruitConfiguration_Dump(YBWCManager_Instance()->pFruitConfiguration);

          YBWCManager_LoadLogSettings(YBWCManager_Instance(), LogSettings_Instance());
*/
        }

        square_init();
        piece_init();
        pawn_init_bit();
        value_init();
        vector_init();
        attack_init();
        move_do_init();

        random_init();
        hash_init();

        trans_init(Trans);
        book_init();

// kh 10.04.07 Thomas Gaksch
	      egbb_cache_size = (egbb_cache_size * 1024 * 1024);

#if defined(_WIN32) || defined(_WIN64)

        egbb_is_loaded = (LoadEgbbLibrary(egbb_path,egbb_cache_size) != 0); // kh 10.04.07 avoid compiler warning

#else // assume POSIX

        egbb_is_loaded = false;

#endif

	      if(egbb_is_loaded)
        {
        }
        else
        {
		      YBWCManager_Printf(YBWCManager_Instance(), "EgbbProbe not Loaded!\n");
        }

        // loop

        loop();
      }

      nExitResult = EXIT_SUCCESS;
    }
    else
    {
      if(YBWCManager_Instance()->pCommandLine->bExitRequest)
      {
        // kh 28.07.06 suppress error messages from command line parse
      }
      else
      {

// kh 21.07.06 eventually pFruitConfiguration is not accessible due to the error
//      if(YBWCManager_Instance()->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
        {
          YBWCManager_Printf(YBWCManager_Instance(), "ERROR YBWCManager_Init(... failed, errorcode = %d\n", nResult);
        }
      }
    }

    YBWCManager_Printf(YBWCManager_Instance(), "finalizing environment...\n");

    YBWCManager_SaveLogSettings(YBWCManager_Instance(), LogSettings_Instance());
    YBWCManager_Destruct(YBWCManager_Instance());
  }
  else
  {

// kh 05.07.06 pFruitConfiguration is not yet accessible here
//  if(YBWCManager_Instance()->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
    {

// kh 04.08.06 defensive, e.g. nRank will be -1 anyway
      YBWCManager_LoadLogSettings(YBWCManager_Instance(), LogSettings_Instance());

      YBWCManager_Printf(YBWCManager_Instance(), "ERROR MPI init failed, errorcode = %d\n", nResult);
      YBWCManager_Destruct(YBWCManager_Instance());
    }
  }

  nResult = MPIWrapper_Finalize(MPIWrapper_Instance());
  if(nResult == MPI_SUCCESS)
  {
  }
  else
  {

// kh 05.07.06 pFruitConfiguration is no longer accessible here
//  if(YBWCManager_Instance()->pFruitConfiguration->nFruitDebugLevel >= FRUIT_DEBUG_LEVEL_ERROR_PRIO_1)
    {
      YBWCManager_LoadLogSettings(YBWCManager_Instance(), LogSettings_Instance());
      YBWCManager_Printf(YBWCManager_Instance(), "ERROR MPI finalize failed, errorcode = %d\n", nResult);
      YBWCManager_Destruct(YBWCManager_Instance());
    }
  }

  MPIWrapper_Destruct(MPIWrapper_Instance());

  YBWCManager_LoadLogSettings(YBWCManager_Instance(), LogSettings_Instance());
  YBWCManager_Printf(YBWCManager_Instance(), "done\n", nResult);

  finalize(); 

  YBWCManager_Destruct(YBWCManager_Instance());
  CommPrinter_Destruct(CommPrinter_Instance());
  LogSettings_Destruct(LogSettings_Instance());

  return nExitResult;
}

// end of main.cpp
