#ifndef __MASTER_SLAVES__
#define __MASTER_SLAVES__

#include "Cache_Server.hpp"

using namespace NOMAD;
using namespace std;

// Cache server:
class Master_Slaves {
    
private:
    
    int                  _rank; // process rank
    int                    _np; // number of processes
    
    int                   _bbe; // max number of evaluations for each process
    int                    _ns; // number of free variables for each process
    
    Parameters            & _p; // parameters
    bool                _debug; // debug display flag
    
    Evaluator             & _ev; // Evaluator
    
    static const int  TAG_SIGNAL;
    static const int  TAG_I1;
    static const int  TAG_I2;
    static const int  TAG_R1;
    static const int  TAG_D1;
    static const int  TAG_CSTOP;
    static       char STOP_SIGNAL;
    static       char OPTI_RES_SIGNAL;
    static       char OPTI_DATA_SIGNAL;
    
    // Receive an optimization result from the pollster:
    void receive_optimization_result ( int       & pollster_mesh_index ,
                                      bool      & stop_algo           ,
                                      double   *& best_feasible       ,
                                      double   *& best_infeasible     ,
                                      int         source ) const;
    
    // Send an optimization result to the master:
    void send_optimization_result ( int                pollster_mesh_index ,
                                   bool               stop_algo           ,
                                   const Eval_Point * bf                  ,
                                   const Eval_Point * bi                  ,
                                   stop_type          st ) const;
    
    // Send optimization data from the master to a slave:
    void send_optimization_data ( int            pollster_mesh_index ,
                                 bool           stop_algo           ,
                                 const double * best_feasible       ,
                                 const double * best_infeasible     ,
                                 int            source ) const;
    
    // Receive optimization data from the master:
    void receive_optimization_data ( bool   & stop_algo ,
                                    Point  & x0        ,
                                    Double & fx0 ) const;
    
    void receive_optimization_data ( bool   & stop_algo           ,
                                    Point  & x0                  ,
                                    Double & fx0                 ,
                                    int    & pollster_mesh_index ,
                                    int    * free_vars ) const;
    
    // Check the initial mesh size values:
    static bool check_delta ( const Point & delta );
    
public:
    
    // Constructor:
    Master_Slaves ( int       rank ,
                   int         np ,
                   int        bbe ,
                   int         ns ,
                   Parameters & p ,
                   bool     debug ,
                   Evaluator &ev  )
    : _rank               ( rank                              ) ,
    _np                 ( np                                ) ,
    _bbe                ( bbe                               ) ,
    _ns                 ( ns                                ) ,
    _p                  ( p                                 ) ,
    _debug                ( debug                             ) ,
    _ev                   ( ev                                ){}
    
    // Destructor:
    virtual ~Master_Slaves ( void ) {}
    
    // Start the master:
    void start ( void ) const;
    
    // Stop the master:
    void stop ( void ) const;
    
    // MADS run:
    void mads_run ( Cache & cache );
    
};


#endif
