/* This file is part of cardwords
   (c) 1999 Tobias Peters
   see file COPYING for the copyright terms.
   
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

// cardwords_baseclient.hh

#ifndef CARDWORDS_BASECLIENT_HH
#define CARDWORDS_BASECLIENT_HH

#include "cardwords_tcpclient.hh"

// The class CardWords_BaseClient can serve in any cardwords client as the
// communication unit. It sends messages to the cardwords_server over a tcp
// network and receives messages from the server.
// It is, however, an abstract base class. Every different client
// might have a different method of notifiyng the CardWords_BaseClient that
// their is data pending on the network connection or that it is possible to
// write data.
// Some widget sets for Xwindows have their own main loop that includes a
// select(2) call. These have their own function call interface to notify
// about the io possibility.
// Please look at CardWords_GtkClient for an example on how to use a widget
// set's main loop.

// Use the following aproach:
// The BaseClient will always be registered for reading from the socket fd
// from the moment of establishing the connection on. Every message from the
// server will be received this way.
// The BaseClient will be registered for writing only if it has a message to
// send. After sending the message is finished, it deregisters from writing.

class CardWords_BaseClient : public CardWords_TCPClient {
public:
  CardWords_BaseClient();
  virtual ~CardWords_BaseClient();
  
  // Functions for registering this object's fd in the main select(2) call.
  // Call CardWords_BaseClient::(de)register_* from your corresponding method,
  // it will set the is_registered_for_*() flags correctly.
  virtual void
  register_reading(void);

  virtual void
  register_writing(void);

  virtual void
  deregister_reading(void);

  // If you want to discard all pending messages, use discard_messages() prior
  // to deregister_writing()
  virtual void
  deregister_writing(void);

  // This function stops the communication with the server immediately. Should
  // only be used when the connection breaks.
  virtual void
  discard_messages(void);
  
  // The current registered status:
  bool is_registered_for_reading(void);
  bool is_registered_for_writing(void);

  void
  send_message(const string &);

  // Call this method when writing is possible:
  void
  send_now(void);

  // Call this methot when reading is possible:
  void
  read_now(void); // This will call the following virtual method
  //                 when a complete message has been received:

  // Overwrite this method with your callback to a complete network
  // message:
  virtual void
  received_complete_message(char message_type_indicator,
                                // see cardwords_server.hh,
                                // MESSAGE_*_INDICATOR,
                   
                            const string & message);

  // disconnect() discards pending messages, deregisters and closes the
  // TCP connection
  virtual void
  disconnect(void);
  
private:
  string message_to_send;
  bool registered_for_reading;
  bool registered_for_writing;

  bool receiving_header;
  bool receiving_body;
  size_t bytes_expected;
  string received_message;
  char message_type;
#ifdef DEBUG_NETWORK_TRAFFIC
  string last_received_message;
#endif
};
  
#endif // CARDWORDS_BASECLIENT_HH
