// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/cast_channel/cast_message_util.h"

#include <memory>

#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "build/build_config.h"
#include "components/cast_channel/cast_auth_util.h"
#include "components/cast_channel/proto/cast_channel.pb.h"

using base::Value;

namespace cast_channel {

namespace {
// Text payload keys.
constexpr char kTypeNodeId[] = "type";
constexpr char kRequestIdNodeId[] = "requestId";

// Cast application protocol message types. Keep in sync with CastMessageType.
constexpr char kKeepAlivePingType[] = "PING";
constexpr char kKeepAlivePongType[] = "PONG";
constexpr char kGetAppAvailabilityRequestType[] = "GET_APP_AVAILABILITY";
constexpr char kConnectionRequestType[] = "CONNECT";
constexpr char kCloseConnectionRequestType[] = "CLOSE";
constexpr char kBroadcastRequestType[] = "APPLICATION_BROADCAST";
constexpr char kLaunchRequestType[] = "LAUNCH";
constexpr char kStopRequestType[] = "STOP";
constexpr char kReceiverStatusType[] = "RECEIVER_STATUS";
constexpr char kLaunchErrorType[] = "LAUNCH_ERROR";

// The value used for "sdkType" in a virtual connect request. Historically, this
// value is used in the Media Router extension, but here it is reused in Chrome.
constexpr int kVirtualConnectSdkType = 2;

// The value used for "connectionType" in a virtual connect request. This value
// stands for CONNECTION_TYPE_LOCAL, which is the only type used in Chrome.
constexpr int kVirtualConnectTypeLocal = 1;

void FillCommonCastMessageFields(CastMessage* message,
                                 const std::string& source_id,
                                 const std::string& destination_id,
                                 const std::string& message_namespace) {
  message->set_protocol_version(CastMessage::CASTV2_1_0);
  message->set_source_id(source_id);
  message->set_destination_id(destination_id);
  message->set_namespace_(message_namespace);
}

CastMessage CreateKeepAliveMessage(const char* keep_alive_type) {
  base::Value type_dict(base::Value::Type::DICTIONARY);
  type_dict.SetKey(kTypeNodeId, base::Value(keep_alive_type));
  return CreateCastMessage(kHeartbeatNamespace, type_dict, kPlatformSenderId,
                           kPlatformReceiverId);
}

// Returns the value to be set as the "platform" value in a virtual connect
// request. The value is platform-dependent and is taken from the Platform enum
// defined in third_party/metrics_proto/cast_logs.proto.
int GetVirtualConnectPlatformValue() {
#if defined(OS_WIN)
  return 3;
#elif defined(OS_MACOSX)
  return 4;
#elif defined(OS_CHROMEOS)
  return 5;
#elif defined(OS_LINUX)
  return 6;
#else
  return 0;
#endif
}

}  // namespace

bool IsCastMessageValid(const CastMessage& message_proto) {
  if (!message_proto.IsInitialized())
    return false;

  if (message_proto.namespace_().empty() || message_proto.source_id().empty() ||
      message_proto.destination_id().empty()) {
    return false;
  }
  return (message_proto.payload_type() == CastMessage_PayloadType_STRING &&
          message_proto.has_payload_utf8()) ||
         (message_proto.payload_type() == CastMessage_PayloadType_BINARY &&
          message_proto.has_payload_binary());
}

bool IsCastInternalNamespace(const std::string& message_namespace) {
  // Note: any namespace with the prefix is assumed to be reserved for internal
  // messages.
  return base::StartsWith(message_namespace, kCastInternalNamespacePrefix,
                          base::CompareCase::SENSITIVE);
}

CastMessageType ParseMessageTypeFromPayload(const base::Value& payload) {
  const Value* type_string =
      payload.FindKeyOfType(kTypeNodeId, Value::Type::STRING);
  return type_string ? CastMessageTypeFromString(type_string->GetString())
                     : CastMessageType::kOther;
}

const char* CastMessageTypeToString(CastMessageType message_type) {
  switch (message_type) {
    case CastMessageType::kPing:
      return kKeepAlivePingType;
    case CastMessageType::kPong:
      return kKeepAlivePongType;
    case CastMessageType::kGetAppAvailability:
      return kGetAppAvailabilityRequestType;
    case CastMessageType::kConnect:
      return kConnectionRequestType;
    case CastMessageType::kCloseConnection:
      return kCloseConnectionRequestType;
    case CastMessageType::kBroadcast:
      return kBroadcastRequestType;
    case CastMessageType::kLaunch:
      return kLaunchRequestType;
    case CastMessageType::kStop:
      return kStopRequestType;
    case CastMessageType::kReceiverStatus:
      return kReceiverStatusType;
    case CastMessageType::kLaunchError:
      return kLaunchErrorType;
    case CastMessageType::kOther:
      return "";
  }
  NOTREACHED();
  return "";
}

CastMessageType CastMessageTypeFromString(const std::string& type) {
  if (type == kKeepAlivePingType)
    return CastMessageType::kPing;
  if (type == kKeepAlivePongType)
    return CastMessageType::kPong;
  if (type == kGetAppAvailabilityRequestType)
    return CastMessageType::kGetAppAvailability;
  if (type == kConnectionRequestType)
    return CastMessageType::kConnect;
  if (type == kCloseConnectionRequestType)
    return CastMessageType::kCloseConnection;
  if (type == kBroadcastRequestType)
    return CastMessageType::kBroadcast;
  if (type == kLaunchRequestType)
    return CastMessageType::kLaunch;
  if (type == kStopRequestType)
    return CastMessageType::kStop;
  if (type == kReceiverStatusType)
    return CastMessageType::kReceiverStatus;
  if (type == kLaunchErrorType)
    return CastMessageType::kLaunchError;

  DVLOG(1) << "Unknown message type: " << type;
  return CastMessageType::kOther;
}

std::string CastMessageToString(const CastMessage& message_proto) {
  std::string out("{");
  out += "namespace = " + message_proto.namespace_();
  out += ", sourceId = " + message_proto.source_id();
  out += ", destId = " + message_proto.destination_id();
  out += ", type = " + base::IntToString(message_proto.payload_type());
  out += ", str = \"" + message_proto.payload_utf8() + "\"}";
  return out;
}

std::string AuthMessageToString(const DeviceAuthMessage& message) {
  std::string out("{");
  if (message.has_challenge()) {
    out += "challenge: {}, ";
  }
  if (message.has_response()) {
    out += "response: {signature: (";
    out += base::NumberToString(message.response().signature().length());
    out += " bytes), certificate: (";
    out += base::NumberToString(
        message.response().client_auth_certificate().length());
    out += " bytes)}";
  }
  if (message.has_error()) {
    out += ", error: {";
    out += base::IntToString(message.error().error_type());
    out += "}";
  }
  out += "}";
  return out;
}

void CreateAuthChallengeMessage(CastMessage* message_proto,
                                const AuthContext& auth_context) {
  CHECK(message_proto);
  DeviceAuthMessage auth_message;

  AuthChallenge* challenge = auth_message.mutable_challenge();
  DCHECK(challenge);
  challenge->set_sender_nonce(auth_context.nonce());
  challenge->set_hash_algorithm(SHA256);

  std::string auth_message_string;
  auth_message.SerializeToString(&auth_message_string);

  FillCommonCastMessageFields(message_proto, kPlatformSenderId,
                              kPlatformReceiverId, kAuthNamespace);
  message_proto->set_payload_type(CastMessage_PayloadType_BINARY);
  message_proto->set_payload_binary(auth_message_string);
}

bool IsAuthMessage(const CastMessage& message) {
  return message.namespace_() == kAuthNamespace;
}

bool IsReceiverMessage(const CastMessage& message) {
  return message.namespace_() == kReceiverNamespace;
}

bool IsPlatformSenderMessage(const CastMessage& message) {
  return message.destination_id() != cast_channel::kPlatformSenderId;
}

CastMessage CreateKeepAlivePingMessage() {
  return CreateKeepAliveMessage(kKeepAlivePingType);
}

CastMessage CreateKeepAlivePongMessage() {
  return CreateKeepAliveMessage(kKeepAlivePongType);
}

CastMessage CreateVirtualConnectionRequest(
    const std::string& source_id,
    const std::string& destination_id,
    VirtualConnectionType connection_type,
    const std::string& user_agent,
    const std::string& browser_version) {
  DCHECK(destination_id != kPlatformReceiverId || connection_type == kStrong);

  // Parse system_version from user agent string. It contains platform, OS and
  // CPU info and is contained in the first set of parentheses of the user
  // agent string (e.g., X11; Linux x86_64).
  std::string system_version;
  size_t start_index = user_agent.find('(');
  if (start_index != std::string::npos) {
    size_t end_index = user_agent.find(')', start_index + 1);
    if (end_index != std::string::npos) {
      system_version =
          user_agent.substr(start_index + 1, end_index - start_index - 1);
    }
  }

  Value dict(Value::Type::DICTIONARY);
  dict.SetKey(kTypeNodeId, Value(kConnectionRequestType));
  dict.SetKey("userAgent", Value(user_agent));
  dict.SetKey("connType", Value(connection_type));
  dict.SetKey("origin", Value(Value::Type::DICTIONARY));

  Value sender_info(Value::Type::DICTIONARY);
  sender_info.SetKey("sdkType", Value(kVirtualConnectSdkType));
  sender_info.SetKey("version", Value(browser_version));
  sender_info.SetKey("browserVersion", Value(browser_version));
  sender_info.SetKey("platform", Value(GetVirtualConnectPlatformValue()));
  sender_info.SetKey("connectionType", Value(kVirtualConnectTypeLocal));
  if (!system_version.empty())
    sender_info.SetKey("systemVersion", Value(system_version));

  dict.SetKey("senderInfo", std::move(sender_info));

  return CreateCastMessage(kConnectionNamespace, dict, source_id,
                           destination_id);
}

CastMessage CreateGetAppAvailabilityRequest(const std::string& source_id,
                                            int request_id,
                                            const std::string& app_id) {
  Value dict(Value::Type::DICTIONARY);
  dict.SetKey(kTypeNodeId, Value(kGetAppAvailabilityRequestType));
  Value app_id_value(Value::Type::LIST);
  app_id_value.GetList().push_back(Value(app_id));
  dict.SetKey("appId", std::move(app_id_value));
  dict.SetKey(kRequestIdNodeId, Value(request_id));

  return CreateCastMessage(kReceiverNamespace, dict, source_id,
                           kPlatformReceiverId);
}

BroadcastRequest::BroadcastRequest(const std::string& broadcast_namespace,
                                   const std::string& message)
    : broadcast_namespace(broadcast_namespace), message(message) {}
BroadcastRequest::~BroadcastRequest() = default;

bool BroadcastRequest::operator==(const BroadcastRequest& other) const {
  return broadcast_namespace == other.broadcast_namespace &&
         message == other.message;
}

CastMessage CreateBroadcastRequest(const std::string& source_id,
                                   int request_id,
                                   const std::vector<std::string>& app_ids,
                                   const BroadcastRequest& request) {
  Value dict(Value::Type::DICTIONARY);
  dict.SetKey(kTypeNodeId, Value(kBroadcastRequestType));
  std::vector<Value> app_ids_value;
  for (const std::string& app_id : app_ids)
    app_ids_value.push_back(Value(app_id));

  dict.SetKey("appIds", Value(std::move(app_ids_value)));
  dict.SetKey("namespace", Value(request.broadcast_namespace));
  dict.SetKey("message", Value(request.message));
  return CreateCastMessage(kBroadcastNamespace, dict, source_id,
                           kPlatformReceiverId);
}

CastMessage CreateLaunchRequest(const std::string& source_id,
                                int request_id,
                                const std::string& app_id,
                                const std::string& locale) {
  Value dict(Value::Type::DICTIONARY);
  dict.SetKey(kTypeNodeId, Value(kLaunchRequestType));
  dict.SetKey(kRequestIdNodeId, Value(request_id));
  dict.SetKey("appId", Value(app_id));
  dict.SetKey("language", Value(locale));

  return CreateCastMessage(kReceiverNamespace, dict, source_id,
                           kPlatformReceiverId);
}

CastMessage CreateStopRequest(const std::string& source_id,
                              int request_id,
                              const std::string& session_id) {
  Value dict(Value::Type::DICTIONARY);
  dict.SetKey(kTypeNodeId, Value(kStopRequestType));
  dict.SetKey(kRequestIdNodeId, Value(request_id));
  dict.SetKey("sessionId", Value(session_id));
  return CreateCastMessage(kReceiverNamespace, dict, source_id,
                           kPlatformReceiverId);
}

CastMessage CreateCastMessage(const std::string& message_namespace,
                              const base::Value& message,
                              const std::string& source_id,
                              const std::string& destination_id) {
  CastMessage output;
  FillCommonCastMessageFields(&output, source_id, destination_id,
                              message_namespace);
  output.set_payload_type(
      CastMessage::PayloadType::CastMessage_PayloadType_STRING);
  CHECK(base::JSONWriter::Write(message, output.mutable_payload_utf8()));
  return output;
}

const char* GetAppAvailabilityResultToString(GetAppAvailabilityResult result) {
  switch (result) {
    case GetAppAvailabilityResult::kAvailable:
      return "available";
    case GetAppAvailabilityResult::kUnavailable:
      return "unavailable";
    case GetAppAvailabilityResult::kUnknown:
      return "unknown";
  }
}

bool GetRequestIdFromResponse(const Value& payload, int* request_id) {
  DCHECK(request_id);
  DCHECK(payload.is_dict());

  const Value* request_id_value =
      payload.FindKeyOfType(kRequestIdNodeId, Value::Type::INTEGER);
  if (!request_id_value)
    return false;

  *request_id = request_id_value->GetInt();
  return true;
}

GetAppAvailabilityResult GetAppAvailabilityResultFromResponse(
    const Value& payload,
    const std::string& app_id) {
  DCHECK(payload.is_dict());
  const Value* availability_value =
      payload.FindPathOfType({"availability", app_id}, Value::Type::STRING);
  if (!availability_value)
    return GetAppAvailabilityResult::kUnknown;

  if (availability_value->GetString() == "APP_AVAILABLE")
    return GetAppAvailabilityResult::kAvailable;
  if (availability_value->GetString() == "APP_UNAVAILABLE")
    return GetAppAvailabilityResult::kUnavailable;

  return GetAppAvailabilityResult::kUnknown;
}

LaunchSessionResponse::LaunchSessionResponse() {}
LaunchSessionResponse::LaunchSessionResponse(LaunchSessionResponse&& other) =
    default;
LaunchSessionResponse::~LaunchSessionResponse() = default;

LaunchSessionResponse GetLaunchSessionResponse(const base::Value& payload) {
  const Value* type_value =
      payload.FindKeyOfType(kTypeNodeId, Value::Type::STRING);
  if (!type_value)
    return LaunchSessionResponse();

  if (type_value->GetString() != kReceiverStatusType &&
      type_value->GetString() != kLaunchErrorType)
    return LaunchSessionResponse();

  LaunchSessionResponse response;
  if (type_value->GetString() == kLaunchErrorType) {
    response.result = LaunchSessionResponse::Result::kError;
    return response;
  }

  const Value* receiver_status =
      payload.FindKeyOfType("status", Value::Type::DICTIONARY);
  if (!receiver_status)
    return LaunchSessionResponse();

  response.result = LaunchSessionResponse::Result::kOk;
  response.receiver_status = receiver_status->Clone();
  return response;
}

}  // namespace cast_channel
