// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.

#ifndef __MESOS_TYPE_UTILS_H__
#define __MESOS_TYPE_UTILS_H__

#include <iosfwd>
#include <string>
#include <vector>

#include <boost/functional/hash.hpp>

#include <google/protobuf/map.h>
#include <google/protobuf/repeated_field.h>

#include <google/protobuf/util/message_differencer.h>

#include <mesos/mesos.hpp>

#include <stout/option.hpp>
#include <stout/stringify.hpp>
#include <stout/strings.hpp>
#include <stout/uuid.hpp>

// This file includes definitions for operators on public protobuf
// classes (defined in mesos.proto, module.proto, etc.) that don't
// have these operators generated by the protobuf compiler. The
// corresponding definitions are in src/common/type_utils.cpp.
//
// Mesos modules need some of the protobuf classes defined in
// mesos.proto, module.proto, etc., and require some of these
// operators declared in type_utils.hpp. Exposing type_utils.hpp
// allows us to build modules without having a dependency on mesos
// source tree (src/*).

namespace mesos {

bool operator==(const CheckStatusInfo& left, const CheckStatusInfo& right);
bool operator==(const CommandInfo& left, const CommandInfo& right);
bool operator==(const CommandInfo::URI& left, const CommandInfo::URI& right);
bool operator==(const ContainerID& left, const ContainerID& right);
bool operator==(const ContainerInfo& left, const ContainerInfo& right);
bool operator==(const Credential& left, const Credential& right);
bool operator==(const CSIPluginInfo& left, const CSIPluginInfo& right);

bool operator==(
    const CSIPluginContainerInfo& left,
    const CSIPluginContainerInfo& right);

bool operator==(const DiscoveryInfo& left, const DiscoveryInfo& right);
bool operator==(const Environment& left, const Environment& right);
bool operator==(const ExecutorInfo& left, const ExecutorInfo& right);
bool operator==(const HealthCheck& left, const HealthCheck& right);
bool operator==(const KillPolicy& left, const KillPolicy& right);
bool operator==(const Label& left, const Label& right);
bool operator==(const Labels& left, const Labels& right);
bool operator==(const MasterInfo& left, const MasterInfo& right);
bool operator==(const Offer::Operation& left, const Offer::Operation& right);
bool operator==(const Operation& left, const Operation& right);
bool operator==(const OperationStatus& left, const OperationStatus& right);

bool operator==(
    const ResourceProviderInfo& left,
    const ResourceProviderInfo& right);

bool operator==(
    const ResourceStatistics& left,
    const ResourceStatistics& right);

bool operator==(const SlaveInfo& left, const SlaveInfo& right);
bool operator==(const Task& left, const Task& right);
bool operator==(const TaskGroupInfo& left, const TaskGroupInfo& right);
bool operator==(const TaskInfo& left, const TaskInfo& right);
bool operator==(const TaskStatus& left, const TaskStatus& right);
bool operator==(const URL& left, const URL& right);
bool operator==(const UUID& left, const UUID& right);
bool operator==(const Volume& left, const Volume& right);
bool operator==(
    const Volume::Source::CSIVolume::VolumeCapability& left,
    const Volume::Source::CSIVolume::VolumeCapability& right);

bool operator!=(const CheckStatusInfo& left, const CheckStatusInfo& right);
bool operator!=(const ExecutorInfo& left, const ExecutorInfo& right);
bool operator!=(const Labels& left, const Labels& right);
bool operator!=(const Offer::Operation& left, const Offer::Operation& right);
bool operator!=(const Operation& left, const Operation& right);
bool operator!=(const OperationStatus& left, const OperationStatus& right);

bool operator!=(const TaskStatus& left, const TaskStatus& right);
bool operator!=(
    const Volume::Source::CSIVolume::VolumeCapability& left,
    const Volume::Source::CSIVolume::VolumeCapability& right);

inline bool operator==(const ExecutorID& left, const ExecutorID& right)
{
  return left.value() == right.value();
}


inline bool operator==(const FrameworkID& left, const FrameworkID& right)
{
  return left.value() == right.value();
}


// This operator, which was comparing only `user` and `name` fields,
// has been deleted in favor of `typeutils::equivalent()` function (see below)
// with different semantics.
bool operator==(const FrameworkInfo& left, const FrameworkInfo& right) = delete;


namespace typeutils {

// Returns whether two `FrameworkInfo`s are equivalent for framework
// subscription purposes or not (i.e. whether subscribing a framework with the
// `left` should have the same effects as with the `right`).
bool equivalent(const FrameworkInfo& left, const FrameworkInfo& right);

// Performs the same comparison as `equivalent()` and returns a human-readable
// diff if the `FrameworkInfo`s are not equivalnt.
Option<std::string> diff(const FrameworkInfo& left, const FrameworkInfo& right);

} // namespace typeutils {


inline bool operator==(const OfferID& left, const OfferID& right)
{
  return left.value() == right.value();
}


inline bool operator==(const OperationID& left, const OperationID& right)
{
  return left.value() == right.value();
}


inline bool operator==(
    const ResourceProviderID& left,
    const ResourceProviderID& right)
{
  return left.value() == right.value();
}


inline bool operator==(const SlaveID& left, const SlaveID& right)
{
  return left.value() == right.value();
}


inline bool operator==(const TaskID& left, const TaskID& right)
{
  return left.value() == right.value();
}


inline bool operator==(const TimeInfo& left, const TimeInfo& right)
{
  return left.nanoseconds() == right.nanoseconds();
}


inline bool operator==(const DurationInfo& left, const DurationInfo& right)
{
  return left.nanoseconds() == right.nanoseconds();
}


inline bool operator==(const ContainerID& left, const std::string& right)
{
  return left.value() == right;
}


inline bool operator==(const ExecutorID& left, const std::string& right)
{
  return left.value() == right;
}


inline bool operator==(const FrameworkID& left, const std::string& right)
{
  return left.value() == right;
}


inline bool operator==(const OfferID& left, const std::string& right)
{
  return left.value() == right;
}


inline bool operator==(const SlaveID& left, const std::string& right)
{
  return left.value() == right;
}


inline bool operator==(const TaskID& left, const std::string& right)
{
  return left.value() == right;
}


inline bool operator==(
    const DomainInfo::FaultDomain::RegionInfo& left,
    const DomainInfo::FaultDomain::RegionInfo& right)
{
  return left.name() == right.name();
}


inline bool operator==(
    const DomainInfo::FaultDomain::ZoneInfo& left,
    const DomainInfo::FaultDomain::ZoneInfo& right)
{
  return left.name() == right.name();
}


inline bool operator==(
    const DomainInfo::FaultDomain& left,
    const DomainInfo::FaultDomain& right)
{
  return left.region() == right.region() && left.zone() == right.zone();
}


inline bool operator==(const DomainInfo& left, const DomainInfo& right)
{
  return left.fault_domain() == right.fault_domain();
}


inline bool operator==(const DrainInfo& left, const DrainInfo& right)
{
  return google::protobuf::util::MessageDifferencer::Equals(left, right);
}


inline bool operator==(const DrainConfig& left, const DrainConfig& right)
{
  return google::protobuf::util::MessageDifferencer::Equals(left, right);
}


/**
 * For machines to match, both the `hostname` and `ip` must be equivalent.
 * Hostname is not case sensitive, so it is lowercased before comparison.
 */
inline bool operator==(const MachineID& left, const MachineID& right)
{
  // NOTE: Both fields default to the empty string if they are not specified,
  // so the string comparisons are safe.
  return left.has_hostname() == right.has_hostname() &&
    strings::lower(left.hostname()) == strings::lower(right.hostname()) &&
    left.has_ip() == right.has_ip() &&
    left.ip() == right.ip();
}


inline bool operator!=(const ContainerID& left, const ContainerID& right)
{
  return !(left == right);
}


inline bool operator!=(
    const CSIPluginContainerInfo& left,
    const CSIPluginContainerInfo& right)
{
  return !(left == right);
}


inline bool operator!=(const ExecutorID& left, const ExecutorID& right)
{
  return left.value() != right.value();
}


inline bool operator!=(const FrameworkID& left, const FrameworkID& right)
{
  return left.value() != right.value();
}


inline bool operator!=(const OperationID& left, const OperationID& right)
{
  return left.value() != right.value();
}


inline bool operator!=(
    const ResourceProviderID& left,
    const ResourceProviderID& right)
{
  return left.value() != right.value();
}


inline bool operator!=(const SlaveID& left, const SlaveID& right)
{
  return left.value() != right.value();
}


inline bool operator!=(
    const ResourceProviderInfo& left,
    const ResourceProviderInfo& right)
{
  return !(left == right);
}


inline bool operator!=(const TimeInfo& left, const TimeInfo& right)
{
  return !(left == right);
}


inline bool operator!=(const UUID& left, const UUID& right)
{
  return !(left == right);
}


inline bool operator!=(const DurationInfo& left, const DurationInfo& right)
{
  return !(left == right);
}


inline bool operator!=(
    const DomainInfo::FaultDomain::RegionInfo& left,
    const DomainInfo::FaultDomain::RegionInfo& right)
{
  return left.name() != right.name();
}


inline bool operator<(const ContainerID& left, const ContainerID& right)
{
  return left.value() < right.value();
}


inline bool operator<(const DurationInfo& left, const DurationInfo& right)
{
  return left.nanoseconds() < right.nanoseconds();
}


inline bool operator<(const ExecutorID& left, const ExecutorID& right)
{
  return left.value() < right.value();
}


inline bool operator<(const FrameworkID& left, const FrameworkID& right)
{
  return left.value() < right.value();
}


inline bool operator<(const OfferID& left, const OfferID& right)
{
  return left.value() < right.value();
}


inline bool operator<(const SlaveID& left, const SlaveID& right)
{
  return left.value() < right.value();
}


inline bool operator<(const TaskID& left, const TaskID& right)
{
  return left.value() < right.value();
}


std::ostream& operator<<(
    std::ostream& stream,
    const CapabilityInfo& capabilityInfo);


std::ostream& operator<<(
    std::ostream& stream,
    const DeviceWhitelist& deviceWhitelist);


std::ostream& operator<<(
    std::ostream& stream,
    const CheckStatusInfo& checkStatusInfo);


std::ostream& operator<<(std::ostream& stream, const CommandInfo& commandInfo);


std::ostream& operator<<(std::ostream& stream, const ContainerID& containerId);


std::ostream& operator<<(
    std::ostream& stream,
    const ContainerInfo& containerInfo);


std::ostream& operator<<(std::ostream& stream, const DomainInfo& domainInfo);


std::ostream& operator<<(std::ostream& stream, const DrainConfig& drainConfig);


std::ostream& operator<<(std::ostream& stream, const DrainState& state);


std::ostream& operator<<(std::ostream& stream, const Environment& environment);


std::ostream& operator<<(std::ostream& stream, const ExecutorID& executorId);


std::ostream& operator<<(std::ostream& stream, const ExecutorInfo& executor);


std::ostream& operator<<(std::ostream& stream, const FrameworkID& frameworkId);


std::ostream& operator<<(std::ostream& stream, const MasterInfo& master);


std::ostream& operator<<(std::ostream& stream, const OfferID& offerId);


std::ostream& operator<<(std::ostream& stream, const OperationID& operationId);


std::ostream& operator<<(std::ostream& stream, const OperationState& state);


std::ostream& operator<<(std::ostream& stream, const Operation& operation);


std::ostream& operator<<(std::ostream& stream, const RateLimits& limits);


std::ostream& operator<<(
    std::ostream& stream,
    const ResourceProviderID& resourceProviderId);


std::ostream& operator<<(
    std::ostream& stream,
    const ResourceProviderInfo& resourceProviderInfo);


std::ostream& operator<<(std::ostream& stream, const RLimitInfo& rlimitInfo);


std::ostream& operator<<(std::ostream& stream, const SlaveID& slaveId);


std::ostream& operator<<(std::ostream& stream, const SlaveInfo& slave);


std::ostream& operator<<(std::ostream& stream, const TaskID& taskId);


std::ostream& operator<<(std::ostream& stream, const MachineID& machineId);


std::ostream& operator<<(std::ostream& stream, const TaskInfo& task);


std::ostream& operator<<(std::ostream& stream, const TaskState& state);


std::ostream& operator<<(
    std::ostream& stream,
    const UUID& uuid);


std::ostream& operator<<(std::ostream& stream, const CheckInfo::Type& type);


std::ostream& operator<<(
    std::ostream& stream,
    const CSIPluginContainerInfo::Service& service);


std::ostream& operator<<(
    std::ostream& stream,
    const FrameworkInfo::Capability& capability);


std::ostream& operator<<(std::ostream& stream, const Image::Type& imageType);


std::ostream& operator<<(std::ostream& stream, const Secret::Type& secretType);


std::ostream& operator<<(
    std::ostream& stream,
    const Offer::Operation::Type& operationType);


std::ostream& operator<<(
    std::ostream& stream,
    const Resource::DiskInfo::Source::Type& sourceType);


template <typename T>
inline std::ostream& operator<<(
    std::ostream& stream,
    const std::vector<T>& messages)
{
  stream << "[ ";
  for (auto it = messages.begin(); it != messages.end(); ++it) {
    if (it != messages.begin()) {
      stream << ", ";
    }
    stream << *it;
  }
  stream << " ]";
  return stream;
}

} // namespace mesos {


/**
 * Type utilities for the protobuf library that are not specific to particular
 * protobuf classes. They are defined in the `google::protobuf` namespace for
 * argument-dependent lookup.
 */
namespace google {
namespace protobuf {

template <typename Key, typename Value>
inline bool operator==(
    const Map<Key, Value>& left, const Map<Key, Value>& right)
{
  if (left.size() != right.size()) {
    return false;
  }

  for (auto it = left.begin(); it != left.end(); ++it) {
    auto found = right.find(it->first);
    if (found == right.end() || found->second != it->second) {
      return false;
    }
  }

  return true;
}


template <typename Key, typename Value>
inline bool operator!=(
    const Map<Key, Value>& left, const Map<Key, Value>& right)
{
  return !(left == right);
}


template <typename Key, typename Value>
inline std::ostream& operator<<(
  std::ostream& stream, const Map<Key, Value>& map)
{
  stream << "{ ";
  for (auto it = map.cbegin(); it != map.end(); ++it) {
    if (it != map.cbegin()) {
      stream << ", ";
    }
    stream << it->first << ": " << it->second;
  }
  stream << " }";

  return stream;
}


template <typename T>
inline std::ostream& operator<<(
    std::ostream& stream,
    const RepeatedPtrField<T>& messages)
{
  stream << "[ ";
  for (auto it = messages.begin(); it != messages.end(); ++it) {
    if (it != messages.begin()) {
      stream << ", ";
    }
    stream << *it;
  }
  stream << " ]";
  return stream;
}

} // namespace protobuf {
} // namespace google {


namespace std {

template <>
struct hash<mesos::CommandInfo::URI>
{
  typedef size_t result_type;

  typedef mesos::CommandInfo::URI argument_type;

  result_type operator()(const argument_type& uri) const
  {
    size_t seed = 0;

    if (uri.extract()) {
      seed += 11;
    }

    if (uri.executable()) {
      seed += 2003;
    }

    boost::hash_combine(seed, uri.value());
    boost::hash_combine(seed, uri.output_file());
    return seed;
  }
};


template <>
struct hash<mesos::ContainerID>
{
  typedef size_t result_type;

  typedef mesos::ContainerID argument_type;

  result_type operator()(const argument_type& containerId) const
  {
    size_t seed = 0;
    boost::hash_combine(seed, containerId.value());

    if (containerId.has_parent()) {
      boost::hash_combine(
          seed,
          std::hash<mesos::ContainerID>()(containerId.parent()));
    }

    return seed;
  }
};


template <>
struct hash<mesos::ExecutorID>
{
  typedef size_t result_type;

  typedef mesos::ExecutorID argument_type;

  result_type operator()(const argument_type& executorId) const
  {
    size_t seed = 0;
    boost::hash_combine(seed, executorId.value());
    return seed;
  }
};


template <>
struct hash<mesos::FrameworkID>
{
  typedef size_t result_type;

  typedef mesos::FrameworkID argument_type;

  result_type operator()(const argument_type& frameworkId) const
  {
    size_t seed = 0;
    boost::hash_combine(seed, frameworkId.value());
    return seed;
  }
};


template <>
struct hash<mesos::Image::Type>
{
  typedef size_t result_type;

  typedef mesos::Image::Type argument_type;

  result_type operator()(const argument_type& imageType) const
  {
    // Use the underlying type of the enum as hash value.
    return static_cast<size_t>(imageType);
  }
};


template <>
struct hash<mesos::MachineID>
{
  typedef size_t result_type;

  typedef mesos::MachineID argument_type;

  result_type operator()(const argument_type& machineId) const
  {
    size_t seed = 0;
    boost::hash_combine(seed, strings::lower(machineId.hostname()));
    boost::hash_combine(seed, machineId.ip());
    return seed;
  }
};


template <>
struct hash<mesos::OfferID>
{
  typedef size_t result_type;

  typedef mesos::OfferID argument_type;

  result_type operator()(const argument_type& offerId) const
  {
    size_t seed = 0;
    boost::hash_combine(seed, offerId.value());
    return seed;
  }
};


template <>
struct hash<mesos::OperationID>
{
  typedef size_t result_type;

  typedef mesos::OperationID argument_type;

  result_type operator()(const argument_type& operationId) const
  {
    size_t seed = 0;
    boost::hash_combine(seed, operationId.value());
    return seed;
  }
};


template <>
struct hash<mesos::ResourceProviderID>
{
  typedef size_t result_type;

  typedef mesos::ResourceProviderID argument_type;

  result_type operator()(const argument_type& resourceProviderId) const
  {
    size_t seed = 0;
    boost::hash_combine(seed, resourceProviderId.value());
    return seed;
  }
};


template <>
struct hash<mesos::SlaveID>
{
  typedef size_t result_type;

  typedef mesos::SlaveID argument_type;

  result_type operator()(const argument_type& slaveId) const
  {
    size_t seed = 0;
    boost::hash_combine(seed, slaveId.value());
    return seed;
  }
};


template <>
struct hash<mesos::TaskID>
{
  typedef size_t result_type;

  typedef mesos::TaskID argument_type;

  result_type operator()(const argument_type& taskId) const
  {
    size_t seed = 0;
    boost::hash_combine(seed, taskId.value());
    return seed;
  }
};


template <>
struct hash<mesos::TaskState>
{
  typedef size_t result_type;

  typedef mesos::TaskState argument_type;

  result_type operator()(const argument_type& taskState) const
  {
    // Use the underlying type of the enum as hash value.
    return static_cast<size_t>(taskState);
  }
};


template <>
struct hash<mesos::TaskStatus_Source>
{
  typedef size_t result_type;

  typedef mesos::TaskStatus_Source argument_type;

  result_type operator()(const argument_type& source) const
  {
    // Use the underlying type of the enum as hash value.
    return static_cast<size_t>(source);
  }
};


template <>
struct hash<mesos::TaskStatus_Reason>
{
  typedef size_t result_type;

  typedef mesos::TaskStatus_Reason argument_type;

  result_type operator()(const argument_type& reason) const
  {
    // Use the underlying type of the enum as hash value.
    return static_cast<size_t>(reason);
  }
};


template <>
struct hash<mesos::UUID>
{
  typedef size_t result_type;

  typedef mesos::UUID argument_type;

  result_type operator()(const argument_type& uuid) const
  {
    size_t seed = 0;
    boost::hash_combine(seed, uuid.value());
    return seed;
  }
};


template <>
struct hash<std::pair<mesos::FrameworkID, mesos::ExecutorID>>
{
  typedef size_t result_type;

  typedef std::pair<
      mesos::FrameworkID, mesos::ExecutorID> argument_type;

  result_type operator()(const argument_type& pair) const
  {
    size_t seed = 0;
    boost::hash_combine(seed, std::hash<mesos::FrameworkID>()(pair.first));
    boost::hash_combine(seed, std::hash<mesos::ExecutorID>()(pair.second));
    return seed;
  }
};


template <>
struct hash<std::pair<mesos::FrameworkID, mesos::OperationID>>
{
  typedef size_t result_type;

  typedef std::pair<
      mesos::FrameworkID, mesos::OperationID> argument_type;

  result_type operator()(const argument_type& pair) const
  {
    size_t seed = 0;
    boost::hash_combine(seed, std::hash<mesos::FrameworkID>()(pair.first));
    boost::hash_combine(seed, std::hash<mesos::OperationID>()(pair.second));
    return seed;
  }
};

} // namespace std {

#endif // __MESOS_TYPE_UTILS_H__
