// Copyright 2012 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// A layer for interacting with low-level protocol messages.

#ifndef GOOGLE_CACHEINVALIDATION_IMPL_PROTOCOL_HANDLER_H_
#define GOOGLE_CACHEINVALIDATION_IMPL_PROTOCOL_HANDLER_H_

#include <map>
#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#include "google/cacheinvalidation/include/system-resources.h"
#include "google/cacheinvalidation/deps/scoped_ptr.h"
#include "google/cacheinvalidation/impl/client-protocol-namespace-fix.h"
#include "google/cacheinvalidation/impl/invalidation-client-util.h"
#include "google/cacheinvalidation/impl/proto-helpers.h"
#include "google/cacheinvalidation/impl/recurring-task.h"
#include "google/cacheinvalidation/impl/statistics.h"
#include "google/cacheinvalidation/impl/smearer.h"
#include "google/cacheinvalidation/impl/throttle.h"
#include "google/cacheinvalidation/impl/ticl-message-validator.h"

namespace invalidation {

class ProtocolHandler;

using INVALIDATION_STL_NAMESPACE::make_pair;
using INVALIDATION_STL_NAMESPACE::map;
using INVALIDATION_STL_NAMESPACE::pair;
using INVALIDATION_STL_NAMESPACE::set;
using INVALIDATION_STL_NAMESPACE::string;

/*
 * Representation of a message header for use in a server message.
 */
struct ServerMessageHeader {
 public:
  ServerMessageHeader() {
  }

  /* Initializes an instance. Note that this call *does not* make copies of
   * the pointed-to data. Instances are always allocated inside a ParsedMessage,
   * and the containing ParsedMessage owns the data.
   *
   * Arguments:
   *     init_token - server-sent token.
   *     init_registration_summary - summary over server registration state.
   *     If num_registations is not set, means no registration summary was
   *     received from the server.
   */
  void InitFrom(const string* init_token,
      const RegistrationSummary* init_registration_summary) {
    token_ = init_token;
    registration_summary_ = init_registration_summary;
  }

  const string& token() const {
    return *token_;
  }

  // Returns the registration summary if any.
  const RegistrationSummary* registration_summary() const {
    return registration_summary_;
  }

  // Returns a human-readable representation of this object for debugging.
  string ToString() const;

 private:
  // Server-sent token.
  const string* token_;

  // Summary of the client's registration state at the server.
  const RegistrationSummary* registration_summary_;

  DISALLOW_COPY_AND_ASSIGN(ServerMessageHeader);
};

/*
 * Representation of a message receiver for the server. Such a message is
 * guaranteed to be valid (i.e. checked by the message validator), but
 * the session token is NOT checked.
 */
struct ParsedMessage {
 public:
  ParsedMessage() {
  }

  ServerMessageHeader header;

  /*
   * Each of these fields points to a field in the base_message
   * ServerToClientMessage protobuf. It is non-null iff the corresponding hasYYY
   * method in the protobuf would return true.
   */
  const TokenControlMessage* token_control_message;
  const InvalidationMessage* invalidation_message;
  const RegistrationStatusMessage* registration_status_message;
  const RegistrationSyncRequestMessage* registration_sync_request_message;
  const ConfigChangeMessage* config_change_message;
  const InfoRequestMessage* info_request_message;
  const ErrorMessage* error_message;

  /*
   * Initializes an instance from a |raw_message|. This function makes a copy of
   * the message internally.
   */
  void InitFrom(const ServerToClientMessage& raw_message);

 private:
  ServerToClientMessage base_message;
  DISALLOW_COPY_AND_ASSIGN(ParsedMessage);
};

/*
 * Class that batches messages to be sent to the data center.
 */
class Batcher {
 public:
  Batcher(Logger* logger, Statistics* statistics)
      : logger_(logger), statistics_(statistics) {}

  /* Sets the initialize |message| to be sent to the server. */
  void SetInitializeMessage(const InitializeMessage* message) {
    pending_initialize_message_.reset(message);
  }

  /* Sets the info |message| to be sent to the server. */
  void SetInfoMessage(const InfoMessage* message) {
    pending_info_message_.reset(message);
  }

  /* Adds a registration on |object_id| to be sent to the server. */
  void AddRegistration(const ObjectIdP& object_id,
                       const RegistrationP::OpType& reg_op_type) {
    pending_registrations_[object_id] = reg_op_type;
  }

  /* Adds an acknowledgment of |invalidation| to be sent to the server. */
  void AddAck(const InvalidationP& invalidation) {
    pending_acked_invalidations_.insert(invalidation);
  }

  /* Adds a registration subtree |reg_subtree| to be sent to the server. */
  void AddRegSubtree(const RegistrationSubtree& reg_subtree) {
    pending_reg_subtrees_.insert(reg_subtree);
  }

  /*
   * Builds a message from the batcher state and resets the batcher. Returns
   * whether the message could be built.
   *
   * Note that the returned message does NOT include a header.
   */
  bool ToBuilder(ClientToServerMessage* builder,
      bool has_client_token);

  /*
   * Initializes a registration message based on registrations from
   * |pending_registrations|.
   *
   * REQUIRES: pending_registrations.size() > 0
   */
  void InitRegistrationMessage(RegistrationMessage* reg_message);

  /* Initializes an invalidation ack message based on acks from
   * |pending_acked_invalidations|.
   * <p>
   * REQUIRES: pending_acked_invalidations.size() > 0
   */
  void InitAckMessage(InvalidationMessage* ack_message);

 private:
  Logger* const logger_;

  Statistics* const statistics_;

  /* Set of pending registrations stored as a map for overriding later
   * operations.
   */
  map<ObjectIdP, RegistrationP::OpType, ProtoCompareLess>
      pending_registrations_;

  /* Set of pending invalidation acks. */
  set<InvalidationP, ProtoCompareLess> pending_acked_invalidations_;

  /* Set of pending registration sub trees for registration sync. */
  set<RegistrationSubtree, ProtoCompareLess> pending_reg_subtrees_;

  /* Pending initialization message to send to the server, if any. */
  scoped_ptr<const InitializeMessage> pending_initialize_message_;

  /* Pending info message to send to the server, if any. */
  scoped_ptr<const InfoMessage> pending_info_message_;

  DISALLOW_COPY_AND_ASSIGN(Batcher);
};

/* Listener for protocol events. The protocol client calls these methods when
 * a message is received from the server. It guarantees that the call will be
 * made on the internal thread that the SystemResources provides. When the
 * protocol listener is called, the token has been checked and message
 * validation has been completed (using the {@link TiclMessageValidator2}).
 * That is, all of the methods below can assume that the nonce is null and the
 * server token is valid.
 */
class ProtocolListener {
 public:
  ProtocolListener() {}
  virtual ~ProtocolListener() {}

  /* Records that a message was sent to the server at the current time. */
  virtual void HandleMessageSent() = 0;

  /* Handles a change in network connectivity. */
  virtual void HandleNetworkStatusChange(bool is_online) = 0;

  /* Stores a summary of the current desired registrations. */
  virtual void GetRegistrationSummary(RegistrationSummary* summary) = 0;

  /* Returns the current server-assigned client token, if any. */
  virtual string GetClientToken() = 0;

 private:
  DISALLOW_COPY_AND_ASSIGN(ProtocolListener);
};

// Forward-declare the BatchingTask so that send* methods can take it.
class BatchingTask;

/* Parses messages from the server and calls appropriate functions on the
 * ProtocolListener to handle various types of message content.  Also buffers
 * message data from the client and constructs and sends messages to the server.
 */
class ProtocolHandler {
 public:
  /* Creates an instance.
   *
   * config - configuration for the client
   * resources - resources to use
   * smearer - a smearer to randomize delays
   * statistics - track information about messages sent/received, etc
   * client_type - client typecode
   * application_name - name of the application using the library (for
   *     debugging/monitoring)
   * listener - callback for protocol events
   * msg_validator - validator for protocol messages
   * Caller continues to own space for smearer.
   */
  ProtocolHandler(const ProtocolHandlerConfigP& config,
                  SystemResources* resources,
                  Smearer* smearer, Statistics* statistics,
                  int client_type, const string& application_name,
                  ProtocolListener* listener,
                  TiclMessageValidator* msg_validator);

  /* Initializes |config| with default protocol handler config parameters. */
  static void InitConfig(ProtocolHandlerConfigP* config);

  /* Initializes |config| with protocol handler config parameters for unit
   * tests.
   */
  static void InitConfigForTest(ProtocolHandlerConfigP* config);

  /* Returns the next time a message is allowed to be sent to the server.
   * Typically, this will be in the past, meaning that the client is free to
   * send a message at any time.
   */
  int64 GetNextMessageSendTimeMsForTest() {
    return next_message_send_time_ms_;
  }

  /* Sends a message to the server to request a client token.
   *
   * Arguments:
   * client_type - client type code as assigned by the notification system's
   *     backend
   * application_client_id - application-specific client id
   * nonce - nonce for the request
   * batching_task - recurring task to trigger batching. No ownership taken.
   * debug_string - information to identify the caller
   */
  void SendInitializeMessage(
      const ApplicationClientIdP& application_client_id,
      const string& nonce,
      BatchingTask* batching_task,
      const string& debug_string);

  /* Sends an info message to the server with the performance counters supplied
   * in performance_counters and the config supplies in client_config (which
   * could be null).
   */
  void SendInfoMessage(const vector<pair<string, int> >& performance_counters,
                       ClientConfigP* client_config,
                       bool request_server_registration_summary,
                       BatchingTask* batching_task);

  /* Sends a registration request to the server.
   *
   * Arguments:
   * object_ids - object ids on which to (un)register
   * reg_op_type - whether to register or unregister
   * batching_task - recurring task to trigger batching. No ownership taken.
   */
  void SendRegistrations(const vector<ObjectIdP>& object_ids,
                         RegistrationP::OpType reg_op_type,
                         BatchingTask* batching_task);

  /* Sends an acknowledgement for invalidation to the server. */
  void SendInvalidationAck(const InvalidationP& invalidation,
                           BatchingTask* batching_task);

  /* Sends a single registration subtree to the server.
   *
   * Arguments:
   * reg_subtree - subtree to send
   * batching_task - recurring task to trigger batching. No ownership taken.
   */
  void SendRegistrationSyncSubtree(const RegistrationSubtree& reg_subtree,
                                   BatchingTask* batching_task);

  /* Sends pending data to the server (e.g., registrations, acks, registration
   * sync messages).
   *
   * REQUIRES: caller do no further work after the method returns.
   */
  void SendMessageToServer();

  /*
   * Handles a message from the server. If the message can be processed (i.e.,
   * is valid, is of the right version, and is not a silence message), returns
   * a ParsedMessage representing it. Otherwise, returns NULL.
   *
   * This class intercepts and processes silence messages. In this case, it will
   * discard any other data in the message.
   *
   * Note that this method does not check the session token of any message.
   */
  bool HandleIncomingMessage(const string& incoming_message,
                             ParsedMessage* parsed_message);

 private:
  /* Verifies that server_token matches the token currently held by the client.
   */
  bool CheckServerToken(const string& server_token);

  /* Stores the header to include on a message to the server. */
  void InitClientHeader(ClientHeader* header);

  // Returns the current time in milliseconds.
  int64 GetCurrentTimeMs() {
    return InvalidationClientUtil::GetCurrentTimeMs(internal_scheduler_);
  }

  friend class BatchingTask;

  // Information about the client, e.g., application name, OS, etc.

  ClientVersion client_version_;

  // A logger.
  Logger* logger_;

  // Scheduler for the client's internal processing.
  Scheduler* internal_scheduler_;

  // Network channel for sending and receiving messages to and from the server.
  NetworkChannel* network_;

  // A throttler to prevent the client from sending too many messages in a given
  // interval.
  Throttle throttle_;

  // The protocol listener.
  ProtocolListener* listener_;

  // Checks that messages (inbound and outbound) conform to basic validity
  // constraints.
  TiclMessageValidator* msg_validator_;

  /* A debug message id that is added to every message to the server. */
  int message_id_;

  // State specific to a client. If we want to support multiple clients, this
  // could be in a map or could be eliminated (e.g., no batching).

  /* The last known time from the server. */
  int64 last_known_server_time_ms_;

  /* The next time before which a message cannot be sent to the server. If
   * this is less than current time, a message can be sent at any time.
   */
  int64 next_message_send_time_ms_;

  /* Statistics objects to track number of sent messages, etc. */
  Statistics* statistics_;

  // Batches messages to be sent to the server.
  Batcher batcher_;

  // Type code for the client.
  int client_type_;

  DISALLOW_COPY_AND_ASSIGN(ProtocolHandler);
};

}  // namespace invalidation

#endif  // GOOGLE_CACHEINVALIDATION_IMPL_PROTOCOL_HANDLER_H_
