/** \file
 *
 *  Contains the SimDaemon class declaration.
 *
 *  Copyright (c) 2007,2008,2009 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 */

#ifndef SIMDAEMON_H_
#define SIMDAEMON_H_

#include "io/SocketServer.h"

#include "SimCommsStruct.h"

#include "utils/FastMap.h"
#include "utils/Mutex.h"
#include "utils/Str.h"

class EnvSimulator;

/**
 * 	Combines a EnvSimulator with a SocketServer to provide
 *  either remote, or out-of-process simulation.
 *
 *  Should be run as a daemon.
 *
 *  \ingroup modules_simulator
 */
class SimDaemon
{
public:
    //static const int SOCKET_SERVER_PORT = 54324;
    static const int SOCKET_SERVER_PORT = SIMPORT;

    SimDaemon();
    virtual ~SimDaemon();
    void run()
#ifndef __GAZEBO
    throw( SocketException& )
#endif
    ;

    /**
     * Code borrowed from http://www-theorie.physik.unizh.ch/~dpotter/howto/daemonize
     *
     * To properly daemonize, the following steps must be followed.
     * \li The fork() call is used to create a separate process.
     * \li The setsid() call is used to detach the process from the parent (normally a shell).
     * \li The file mask should be reset.
     * \li The current directory should be changed to something benign.
     *     - We do not do this since we want to open a file at a relative position
     * \li The standard files (stdin,stdout and stderr) need to be reopened.
     *
     * Failure to do any of these steps will lead to a daemon process that can misbehave. The typical symptoms are as follows.
     * \li Starting the daemon and then logging out will cause the terminal to hang. This is particularly nasty with ssh.
     * \li The directory from which the daemon was launched remains locked.
     * \li Spurious output appears in the shell from which the daemon was started.
     */
    static void Daemonize( bool hideOutputs );

    static void SetDebug( bool debug )
    {
        Debug_ = debug;
    }

    static void SetDebugComms( bool debugComms )
    {
        DebugComms_ = debugComms;
    }

private:
    // Note that the copy constructor below is private and not given a body.
    // Any attempt to call it will return a compiler error.
    SimDaemon( const SimDaemon& old ); // disallow copy constructor

    static bool Debug_;
    static bool DebugComms_;
    static bool Shutdown_;
    static Mutex ShutdownMutex_;
    SocketServer* socketServer_;
    static FastMap<uint64_t, EnvSimulator*> SimulatorMap_;
    static void* ServiceClient( void* clientSocketPtr );

    static FlexArray<SimCommsEntry*> SimCommsEntries_;
    static void AddSimCommsEntry( SimCommsEntry* entry );
    static SimCommsEntry* FindSimCommsEntry( Simulator* sim );


};

#endif /*SIMDAEMON_H_*/
