// Copyright 2019 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 "cast/streaming/offer_messages.h"

#include <inttypes.h>

#include <algorithm>
#include <limits>
#include <string>
#include <utility>

#include "absl/strings/match.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_split.h"
#include "cast/streaming/capture_recommendations.h"
#include "cast/streaming/constants.h"
#include "platform/base/error.h"
#include "util/big_endian.h"
#include "util/enum_name_table.h"
#include "util/json/json_helpers.h"
#include "util/json/json_serialization.h"
#include "util/osp_logging.h"
#include "util/stringprintf.h"

namespace openscreen {
namespace cast {

namespace {

constexpr char kSupportedStreams[] = "supportedStreams";
constexpr char kAudioSourceType[] = "audio_source";
constexpr char kVideoSourceType[] = "video_source";
constexpr char kStreamType[] = "type";

ErrorOr<RtpPayloadType> ParseRtpPayloadType(const Json::Value& parent,
                                            const std::string& field) {
  auto t = json::ParseInt(parent, field);
  if (!t) {
    return t.error();
  }

  uint8_t t_small = t.value();
  if (t_small != t.value() || !IsRtpPayloadType(t_small)) {
    return Error(Error::Code::kParameterInvalid,
                 "Received invalid RTP Payload Type.");
  }

  return static_cast<RtpPayloadType>(t_small);
}

ErrorOr<int> ParseRtpTimebase(const Json::Value& parent,
                              const std::string& field) {
  auto error_or_raw = json::ParseString(parent, field);
  if (!error_or_raw) {
    return error_or_raw.error();
  }

  // The spec demands a leading 1, so this isn't really a fraction.
  const auto fraction = SimpleFraction::FromString(error_or_raw.value());
  if (fraction.is_error() || !fraction.value().is_positive() ||
      fraction.value().numerator != 1) {
    return json::CreateParseError("RTP timebase");
  }
  return fraction.value().denominator;
}

// For a hex byte, the conversion is 4 bits to 1 character, e.g.
// 0b11110001 becomes F1, so 1 byte is two characters.
constexpr int kHexDigitsPerByte = 2;
constexpr int kAesBytesSize = 16;
constexpr int kAesStringLength = kAesBytesSize * kHexDigitsPerByte;
ErrorOr<std::array<uint8_t, kAesBytesSize>> ParseAesHexBytes(
    const Json::Value& parent,
    const std::string& field) {
  auto hex_string = json::ParseString(parent, field);
  if (!hex_string) {
    return hex_string.error();
  }

  constexpr int kHexDigitsPerScanField = 16;
  constexpr int kNumScanFields = kAesStringLength / kHexDigitsPerScanField;
  uint64_t quads[kNumScanFields];
  int chars_scanned;
  if (hex_string.value().size() == kAesStringLength &&
      sscanf(hex_string.value().c_str(), "%16" SCNx64 "%16" SCNx64 "%n",
             &quads[0], &quads[1], &chars_scanned) == kNumScanFields &&
      chars_scanned == kAesStringLength &&
      std::none_of(hex_string.value().begin(), hex_string.value().end(),
                   [](char c) { return std::isspace(c); })) {
    std::array<uint8_t, kAesBytesSize> bytes;
    WriteBigEndian(quads[0], bytes.data());
    WriteBigEndian(quads[1], bytes.data() + 8);
    return bytes;
  }
  return json::CreateParseError("AES hex string bytes");
}

ErrorOr<Stream> ParseStream(const Json::Value& value, Stream::Type type) {
  auto index = json::ParseInt(value, "index");
  if (!index) {
    return index.error();
  }
  // If channel is omitted, the default value is used later.
  auto channels = json::ParseInt(value, "channels");
  if (channels.is_value() && channels.value() <= 0) {
    return json::CreateParameterError("channel");
  }
  auto rtp_profile = json::ParseString(value, "rtpProfile");
  if (!rtp_profile) {
    return rtp_profile.error();
  }
  auto rtp_payload_type = ParseRtpPayloadType(value, "rtpPayloadType");
  if (!rtp_payload_type) {
    return rtp_payload_type.error();
  }
  auto ssrc = json::ParseUint(value, "ssrc");
  if (!ssrc) {
    return ssrc.error();
  }
  auto aes_key = ParseAesHexBytes(value, "aesKey");
  if (!aes_key) {
    return aes_key.error();
  }
  auto aes_iv_mask = ParseAesHexBytes(value, "aesIvMask");
  if (!aes_iv_mask) {
    return aes_iv_mask.error();
  }
  auto rtp_timebase = ParseRtpTimebase(value, "timeBase");
  if (!rtp_timebase) {
    return rtp_timebase.error();
  }
  if (rtp_timebase.value() <
          std::min(capture_recommendations::kDefaultAudioMinSampleRate,
                   kRtpVideoTimebase) ||
      rtp_timebase.value() > kRtpVideoTimebase) {
    return json::CreateParameterError("rtp_timebase (sample rate)");
  }

  auto target_delay = json::ParseInt(value, "targetDelay");
  std::chrono::milliseconds target_delay_ms = kDefaultTargetPlayoutDelay;
  if (target_delay) {
    auto d = std::chrono::milliseconds(target_delay.value());
    if (kMinTargetPlayoutDelay <= d && d <= kMaxTargetPlayoutDelay) {
      target_delay_ms = d;
    }
  }

  auto receiver_rtcp_event_log = json::ParseBool(value, "receiverRtcpEventLog");
  auto receiver_rtcp_dscp = json::ParseString(value, "receiverRtcpDscp");
  return Stream{index.value(),
                type,
                channels.value(type == Stream::Type::kAudioSource
                                   ? kDefaultNumAudioChannels
                                   : kDefaultNumVideoChannels),
                rtp_payload_type.value(),
                ssrc.value(),
                target_delay_ms,
                aes_key.value(),
                aes_iv_mask.value(),
                receiver_rtcp_event_log.value({}),
                receiver_rtcp_dscp.value({}),
                rtp_timebase.value()};
}

ErrorOr<AudioStream> ParseAudioStream(const Json::Value& value) {
  auto stream = ParseStream(value, Stream::Type::kAudioSource);
  if (!stream) {
    return stream.error();
  }
  auto bit_rate = json::ParseInt(value, "bitRate");
  if (!bit_rate) {
    return bit_rate.error();
  }

  auto codec_name = json::ParseString(value, "codecName");
  if (!codec_name) {
    return codec_name.error();
  }
  ErrorOr<AudioCodec> codec = StringToAudioCodec(codec_name.value());
  if (!codec) {
    return Error(Error::Code::kUnknownCodec,
                 "Codec is not known, can't use stream");
  }

  // A bit rate of 0 is valid for some codec types, so we don't enforce here.
  if (bit_rate.value() < 0) {
    return json::CreateParameterError("bit rate");
  }
  return AudioStream{stream.value(), codec.value(), bit_rate.value()};
}

ErrorOr<Resolution> ParseResolution(const Json::Value& value) {
  auto width = json::ParseInt(value, "width");
  if (!width) {
    return width.error();
  }
  auto height = json::ParseInt(value, "height");
  if (!height) {
    return height.error();
  }
  if (width.value() <= 0 || height.value() <= 0) {
    return json::CreateParameterError("resolution");
  }
  return Resolution{width.value(), height.value()};
}

ErrorOr<std::vector<Resolution>> ParseResolutions(const Json::Value& parent,
                                                  const std::string& field) {
  std::vector<Resolution> resolutions;
  // Some legacy senders don't provide resolutions, so just return empty.
  const Json::Value& value = parent[field];
  if (!value.isArray() || value.empty()) {
    return resolutions;
  }

  for (Json::ArrayIndex i = 0; i < value.size(); ++i) {
    auto r = ParseResolution(value[i]);
    if (!r) {
      return r.error();
    }
    resolutions.push_back(r.value());
  }

  return resolutions;
}

ErrorOr<VideoStream> ParseVideoStream(const Json::Value& value) {
  auto stream = ParseStream(value, Stream::Type::kVideoSource);
  if (!stream) {
    return stream.error();
  }
  auto codec_name = json::ParseString(value, "codecName");
  if (!codec_name) {
    return codec_name.error();
  }
  ErrorOr<VideoCodec> codec = StringToVideoCodec(codec_name.value());
  if (!codec) {
    return Error(Error::Code::kUnknownCodec,
                 "Codec is not known, can't use stream");
  }
  auto resolutions = ParseResolutions(value, "resolutions");
  if (!resolutions) {
    return resolutions.error();
  }

  auto raw_max_frame_rate = json::ParseString(value, "maxFrameRate");
  SimpleFraction max_frame_rate{kDefaultMaxFrameRate, 1};
  if (raw_max_frame_rate.is_value()) {
    auto parsed = SimpleFraction::FromString(raw_max_frame_rate.value());
    if (parsed.is_value() && parsed.value().is_positive()) {
      max_frame_rate = parsed.value();
    }
  }

  auto profile = json::ParseString(value, "profile");
  auto protection = json::ParseString(value, "protection");
  auto max_bit_rate = json::ParseInt(value, "maxBitRate");
  auto level = json::ParseString(value, "level");
  auto error_recovery_mode = json::ParseString(value, "errorRecoveryMode");
  return VideoStream{stream.value(),
                     codec.value(),
                     max_frame_rate,
                     max_bit_rate.value(4 << 20),
                     protection.value({}),
                     profile.value({}),
                     level.value({}),
                     resolutions.value(),
                     error_recovery_mode.value({})};
}

absl::string_view ToString(Stream::Type type) {
  switch (type) {
    case Stream::Type::kAudioSource:
      return kAudioSourceType;
    case Stream::Type::kVideoSource:
      return kVideoSourceType;
    default: {
      OSP_NOTREACHED();
    }
  }
}

EnumNameTable<CastMode, 2> kCastModeNames{
    {{"mirroring", CastMode::kMirroring}, {"remoting", CastMode::kRemoting}}};

}  // namespace

ErrorOr<Json::Value> Stream::ToJson() const {
  if (channels < 1 || index < 0 || target_delay.count() <= 0 ||
      target_delay.count() > std::numeric_limits<int>::max() ||
      rtp_timebase < 1) {
    return json::CreateParameterError("Stream");
  }

  Json::Value root;
  root["index"] = index;
  root["type"] = std::string(ToString(type));
  root["channels"] = channels;
  root["rtpPayloadType"] = static_cast<int>(rtp_payload_type);
  // rtpProfile is technically required by the spec, although it is always set
  // to cast. We set it here to be compliant with all spec implementers.
  root["rtpProfile"] = "cast";
  static_assert(sizeof(ssrc) <= sizeof(Json::UInt),
                "this code assumes Ssrc fits in a Json::UInt");
  root["ssrc"] = static_cast<Json::UInt>(ssrc);
  root["targetDelay"] = static_cast<int>(target_delay.count());
  root["aesKey"] = HexEncode(aes_key);
  root["aesIvMask"] = HexEncode(aes_iv_mask);
  root["receiverRtcpEventLog"] = receiver_rtcp_event_log;
  root["receiverRtcpDscp"] = receiver_rtcp_dscp;
  root["timeBase"] = "1/" + std::to_string(rtp_timebase);
  return root;
}

ErrorOr<Json::Value> AudioStream::ToJson() const {
  // A bit rate of 0 is valid for some codec types, so we don't enforce here.
  if (bit_rate < 0) {
    return json::CreateParameterError("AudioStream");
  }

  auto error_or_stream = stream.ToJson();
  if (error_or_stream.is_error()) {
    return error_or_stream;
  }

  error_or_stream.value()["codecName"] = CodecToString(codec);
  error_or_stream.value()["bitRate"] = bit_rate;
  return error_or_stream;
}

ErrorOr<Json::Value> Resolution::ToJson() const {
  if (width <= 0 || height <= 0) {
    return json::CreateParameterError("Resolution");
  }

  Json::Value root;
  root["width"] = width;
  root["height"] = height;
  return root;
}

ErrorOr<Json::Value> VideoStream::ToJson() const {
  if (max_bit_rate <= 0 || !max_frame_rate.is_positive()) {
    return json::CreateParameterError("VideoStream");
  }

  auto error_or_stream = stream.ToJson();
  if (error_or_stream.is_error()) {
    return error_or_stream;
  }

  auto& stream = error_or_stream.value();
  stream["codecName"] = CodecToString(codec);
  stream["maxFrameRate"] = max_frame_rate.ToString();
  stream["maxBitRate"] = max_bit_rate;
  stream["protection"] = protection;
  stream["profile"] = profile;
  stream["level"] = level;
  stream["errorRecoveryMode"] = error_recovery_mode;

  Json::Value rs;
  for (auto resolution : resolutions) {
    auto eoj = resolution.ToJson();
    if (eoj.is_error()) {
      return eoj;
    }
    rs.append(eoj.value());
  }
  stream["resolutions"] = std::move(rs);
  return error_or_stream;
}

// static
ErrorOr<Offer> Offer::Parse(const Json::Value& root) {
  if (!root.isObject()) {
    return json::CreateParseError("null offer");
  }
  ErrorOr<CastMode> cast_mode =
      GetEnum(kCastModeNames, root["castMode"].asString());
  const ErrorOr<bool> get_status = json::ParseBool(root, "receiverGetStatus");

  Json::Value supported_streams = root[kSupportedStreams];
  if (!supported_streams.isArray()) {
    return json::CreateParseError("supported streams in offer");
  }

  std::vector<AudioStream> audio_streams;
  std::vector<VideoStream> video_streams;
  for (Json::ArrayIndex i = 0; i < supported_streams.size(); ++i) {
    const Json::Value& fields = supported_streams[i];
    auto type = json::ParseString(fields, kStreamType);
    if (!type) {
      return type.error();
    }

    if (type.value() == kAudioSourceType) {
      auto stream = ParseAudioStream(fields);
      if (!stream) {
        if (stream.error().code() == Error::Code::kUnknownCodec) {
          OSP_DVLOG << "Dropping audio stream due to unknown codec: "
                    << stream.error();
          continue;
        } else {
          return stream.error();
        }
      }
      audio_streams.push_back(std::move(stream.value()));
    } else if (type.value() == kVideoSourceType) {
      auto stream = ParseVideoStream(fields);
      if (!stream) {
        if (stream.error().code() == Error::Code::kUnknownCodec) {
          OSP_DVLOG << "Dropping video stream due to unknown codec: "
                    << stream.error();
          continue;
        } else {
          return stream.error();
        }
      }
      video_streams.push_back(std::move(stream.value()));
    }
  }

  return Offer{cast_mode.value(CastMode::kMirroring), get_status.value({}),
               std::move(audio_streams), std::move(video_streams)};
}

ErrorOr<Json::Value> Offer::ToJson() const {
  Json::Value root;

  root["castMode"] = GetEnumName(kCastModeNames, cast_mode).value();
  root["receiverGetStatus"] = supports_wifi_status_reporting;

  Json::Value streams;
  for (auto& as : audio_streams) {
    auto eoj = as.ToJson();
    if (eoj.is_error()) {
      return eoj;
    }
    streams.append(eoj.value());
  }

  for (auto& vs : video_streams) {
    auto eoj = vs.ToJson();
    if (eoj.is_error()) {
      return eoj;
    }
    streams.append(eoj.value());
  }

  root[kSupportedStreams] = std::move(streams);
  return root;
}

}  // namespace cast
}  // namespace openscreen
