// 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.

// Helper utilities for dealing with protocol buffers.

#ifndef GOOGLE_CACHEINVALIDATION_IMPL_PROTO_HELPERS_H_
#define GOOGLE_CACHEINVALIDATION_IMPL_PROTO_HELPERS_H_

#include <sstream>
#include <string>

#include "google/cacheinvalidation/client_protocol.pb.h"
#include "google/cacheinvalidation/deps/logging.h"
#include "google/cacheinvalidation/deps/stl-namespace.h"
#include "google/cacheinvalidation/impl/client-protocol-namespace-fix.h"
#include "google/cacheinvalidation/impl/constants.h"

namespace invalidation {

using INVALIDATION_STL_NAMESPACE::string;
using ::ipc::invalidation::ProtocolVersion;

// Functor to compare various protocol messages.
struct ProtoCompareLess {
  bool operator()(const ObjectIdP& object_id1,
                  const ObjectIdP& object_id2) const {
    // If the sources differ, then the one with the smaller source is the
    // smaller object id.
    int source_diff = object_id1.source() - object_id2.source();
    if (source_diff != 0) {
      return source_diff < 0;
    }
    // Otherwise, the one with the smaller name is the smaller object id.
    return object_id1.name().compare(object_id2.name()) < 0;
  }

  bool operator()(const InvalidationP& inv1,
                  const InvalidationP& inv2) const {
    const ProtoCompareLess& compare_less_than = *this;
    // If the object ids differ, then the one with the smaller object id is the
    // smaller invalidation.
    if (compare_less_than(inv1.object_id(), inv2.object_id())) {
      return true;
    }
    if (compare_less_than(inv2.object_id(), inv1.object_id())) {
      return false;
    }

    // Otherwise, the object ids are the same, so we need to look at the
    // versions.

    // We define an unknown version to be less than a known version.
    int64 known_version_diff =
        inv1.is_known_version() - inv2.is_known_version();
    if (known_version_diff != 0) {
      return known_version_diff < 0;
    }

    // Otherwise, they're both known both unknown, so the one with the smaller
    // version is the smaller invalidation.
    return inv1.version() < inv2.version();
  }

  bool operator()(const RegistrationSubtree& reg_subtree1,
                  const RegistrationSubtree& reg_subtree2) const {
    const RepeatedPtrField<ObjectIdP>& objects1 =
        reg_subtree1.registered_object();
    const RepeatedPtrField<ObjectIdP>& objects2 =
        reg_subtree2.registered_object();
    // If they have different numbers of objects, the one with fewer is smaller.
    if (objects1.size() != objects2.size()) {
      return objects1.size() < objects2.size();
    }
    // Otherwise, compare the object ids in order.
    RepeatedPtrField<ObjectIdP>::const_iterator iter1, iter2;
    const ProtoCompareLess& compare_less_than = *this;
    for (iter1 = objects1.begin(), iter2 = objects2.begin();
         iter1 != objects1.end(); ++iter1, ++iter2) {
      if (compare_less_than(*iter1, *iter2)) {
        return true;
      }
      if (compare_less_than(*iter2, *iter1)) {
        return false;
      }
    }
    // The registration subtrees are the same.
    return false;
  }
};

// Other protocol message utilities.
class ProtoHelpers {
 public:
  // Converts a value to a printable/readable string format.
  template<typename T>
  static string ToString(const T& value);

  // Initializes |reg| to be a (un) registration for object |oid|.
  static void InitRegistrationP(const ObjectIdP& oid,
      RegistrationP::OpType op_type, RegistrationP* reg);

  static void InitInitializeMessage(
      const ApplicationClientIdP& application_client_id, const string& nonce,
      InitializeMessage* init_msg);

  // Initializes |protocol_version| to the current protocol version.
  static void InitProtocolVersion(ProtocolVersion* protocol_version);

  // Initializes |client_version| to the current client version.
  static void InitClientVersion(const string& platform,
      const string& application_info, ClientVersion* client_version);

  // Initializes |config_version| to the current config version.
  static void InitConfigVersion(Version* config_version);

  // Initializes |rate_limit| with the given window interval and count of
  // messages.
  static void InitRateLimitP(int window_ms, int count, RateLimitP *rate_limit);

 private:
  static const int NUM_CHARS = 256;
  static char CHAR_OCTAL_STRINGS1[NUM_CHARS];
  static char CHAR_OCTAL_STRINGS2[NUM_CHARS];
  static char CHAR_OCTAL_STRINGS3[NUM_CHARS];

  // Have the above arrays been initialized or not.
  static bool is_initialized;
};

}  // namespace invalidation

#endif  // GOOGLE_CACHEINVALIDATION_IMPL_PROTO_HELPERS_H_
