#ifndef RESULT_H
#define RESULT_H

#include "stdmpi.h"

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

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

#else // assume POSIX

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

#endif

#include "FruitBase.h"

#include "StackEntry.h"

#define RESULT_TYPE_UNDEFINED                       0
#define RESULT_TYPE_NON_ROOT_MASTER_LOGON           1
#define RESULT_TYPE_NON_ROOT_MASTER_LOGOFF          2
#define RESULT_TYPE_NON_ROOT_MASTER_SHUTDOWN        3 
#define RESULT_TYPE_NON_ROOT_MASTER_REMOTE_TEST     4
#define RESULT_TYPE_NON_ROOT_MASTER_SYNC_NEW_GAME   5
#define RESULT_TYPE_NON_ROOT_MASTER_SYNC_SET_OPTION 6

#define RESULT_TYPE_MASTER_NO_WORK_AVAILABLE        7
#define RESULT_TYPE_MASTER_WORK_AVAILABLE           8

#define RESULT_TYPE_SYNC_AFTER_BROADCAST            9

#define MAX_RESULT_PARAMETER_BUFFER_SIZE         8192

#define MAX_RESULT_TYPE_TO_STRING                  64

typedef struct tResult
{
  struct tResult* pNext;
  int             nSourceId;
  int             nDestId;
  char            pParameterBuffer    [MAX_RESULT_PARAMETER_BUFFER_SIZE];
  MPI_Request     mpiRequest;
  int             nPosition;

  BOOL            bSendSuppressed;

  int             nType;
  char            szTypeToString      [MAX_RESULT_TYPE_TO_STRING + 1];

  char            sProcessorName      [MPI_MAX_PROCESSOR_NAME + 1];

  int             nBestMove;
  int             nBestValue;
  int             nFlags;
  int             nDepth;
  int             nMaxDepth;

  int             nPVLength;
  uint16          PV[MAX_PV_LENGTH];
  uint16*         pPV;

// kh 12.10.06 no longer used
  int             nPonderMove;

  BOOL            bPonderMoveOk;
  double          dTime;
  double          dSpeed;
  double          dCPU;
  sint64          nNodes;

  int             nSyncPositionId;

  sint64          nWorkId;

  int             nStackIndex;
  int             nMoveListIndex;
  int             nCallType;
  int             nReturnPosition;
  int             nMove;
//int             nDepth;
  int             nNewDepth;
  int             nHeight;
  BOOL            bExtended;
  BOOL            bInPV;
  int             nPlayedNb;
  BOOL            bAlphaBoundIsEstimated; // kh 17.06.08 not really transmitted at the moment, initially set by nPlayedNb == 0
  int             nHistoryValue;
  int             nAlpha;
  int             nBeta;
  int             nTransDate;
  BOOL            bGoodCap; // kh 09.06.08 used only due to "transparent porting"
  int             nMoveAheadListCount;
  uint16          MoveAheadList[MAX_MOVES];
  uint16*         pMoveAheadList;

  int             nKillerListCount;
  uint16          KillerList[MAX_KILLER_ENTRIES];
  uint16*         pKillerList;

  sint64          nTotalNodes;

  int             nHistoryTableSize;
//uint16          HistoryTable[HistorySize];

  int             nHistTotTableSize;
//uint16          HistTotTable[HistorySize];

  int             nHistHitTableSize;
//uint16          HistHitTable[HistorySize];

} Result;

Result* Result_Construct(Result* pThis);

void Result_Destruct(Result* pThis);

int Result_Send(Result* pThis);

BOOL Result_IsSendPending(Result* pThis);

int Result_InitNonRootMasterLogon(Result* pThis);

int Result_InitNonRootMasterLogoff(Result* pThis);

int Result_InitNonRootMasterShutdown(Result* pThis);

int Result_InitNonRootMasterRemoteTest(Result* pThis,
                                       int     nBestMove,
                                       int     nBestValue,
                                       int     nFlags,
                                       int     nDepth,
                                       int     nMaxDepth,
                                       int     nPVLength,
                                       uint16  PV[],
                                       BOOL    bPonderMoveOk,
                                       double  dTime,
                                       double  dSpeed,
                                       double  dCPU,
                                       sint64  nNodes);

int Result_InitNonRootMasterSyncNewGame(Result*  pThis);

int Result_InitNonRootMasterSyncSetOption(Result*  pThis);

int Result_InitSyncAfterBroadcast(Result*  pThis);

int Result_InitMasterNoWorkAvailable(Result* pThis,
                                     int     nSlaveSyncPositionId);

int Result_InitMasterWorkAvailable(Result*  pThis,
                                   int      nStackIndex,
                                   int      nMoveListIndex,
                                   int      nCallType, 
                                   int      nReturnPosition,
                                   int      nMove, 
                                   int      nDepth,
                                   int      nNewDepth,
                                   int      nHeight,
                                   BOOL     bInPV,
                                   int      nPlayedNb,
                                   int      nHistoryValue,
                                   int      nAlpha,
                                   int      nBeta,
                                   int      nTransDate,
                                   BOOL     bGoodCap,
                                   int      nMoveAheadListCount,
                                   uint16   MoveAheadList[],
                                   int      nKillerListCount,
                                   uint16   KillerList[]);

int Result_GetParameterFromBuffer(Result* pThis);

#endif
