/*
 *  Copyright 2024 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "common_video/corruption_detection_converters.h"

#include <optional>
#include <vector>

#include "api/transport/rtp/corruption_detection_message.h"
#include "common_video/frame_instrumentation_data.h"
#include "rtc_base/checks.h"

namespace webrtc {

namespace {

int GetFullSequenceIndex(int previous_sequence_index,
                         int sequence_index_update,
                         bool update_the_most_significant_bits) {
  RTC_CHECK_GE(previous_sequence_index, 0)
      << "previous_sequence_index must not be negative";
  RTC_CHECK_LE(previous_sequence_index, 0x7FFF)
      << "previous_sequence_index must be at most 15 bits";
  RTC_CHECK_GE(sequence_index_update, 0)
      << "sequence_index_update must not be negative";
  RTC_CHECK_LE(sequence_index_update, 0b0111'1111)
      << "sequence_index_update must be at most 7 bits";
  if (update_the_most_significant_bits) {
    // Reset LSB.
    return sequence_index_update << 7;
  }
  int upper_bits = previous_sequence_index & 0b0011'1111'1000'0000;
  if (sequence_index_update < (previous_sequence_index & 0b0111'1111)) {
    // Assume one and only one wraparound has happened.
    upper_bits += 0b1000'0000;
  }
  // Replace the lowest bits with the bits from the update.
  return upper_bits + sequence_index_update;
}

int GetSequenceIndexForMessage(int sequence_index,
                               bool communicate_upper_bits) {
  return communicate_upper_bits ? (sequence_index >> 7)
                                : (sequence_index & 0b0111'1111);
}

}  // namespace

std::optional<FrameInstrumentationData>
ConvertCorruptionDetectionMessageToFrameInstrumentationData(
    const CorruptionDetectionMessage& message,
    int previous_sequence_index) {
  if (previous_sequence_index < 0) {
    return std::nullopt;
  }
  if (message.sample_values().empty()) {
    return std::nullopt;
  }
  int full_sequence_index = GetFullSequenceIndex(
      previous_sequence_index, message.sequence_index(),
      message.interpret_sequence_index_as_most_significant_bits());
  std::vector<double> sample_values(message.sample_values().cbegin(),
                                    message.sample_values().cend());
  return FrameInstrumentationData{
      .sequence_index = full_sequence_index,
      .communicate_upper_bits =
          message.interpret_sequence_index_as_most_significant_bits(),
      .std_dev = message.std_dev(),
      .luma_error_threshold = message.luma_error_threshold(),
      .chroma_error_threshold = message.chroma_error_threshold(),
      .sample_values = sample_values};
}

std::optional<FrameInstrumentationSyncData>
ConvertCorruptionDetectionMessageToFrameInstrumentationSyncData(
    const CorruptionDetectionMessage& message,
    int previous_sequence_index) {
  if (previous_sequence_index < 0) {
    return std::nullopt;
  }
  if (!message.sample_values().empty()) {
    return std::nullopt;
  }
  if (!message.interpret_sequence_index_as_most_significant_bits()) {
    return std::nullopt;
  }
  return FrameInstrumentationSyncData{
      .sequence_index = GetFullSequenceIndex(
          previous_sequence_index, message.sequence_index(),
          /*update_the_most_significant_bits=*/true),
      .communicate_upper_bits = true};
}

std::optional<CorruptionDetectionMessage>
ConvertFrameInstrumentationDataToCorruptionDetectionMessage(
    const FrameInstrumentationData& data) {
  if (data.sequence_index < 0 || data.sequence_index > 0b0011'1111'1111'1111) {
    return std::nullopt;
  }
  // Frame instrumentation data must have sample values.
  if (data.sample_values.empty()) {
    return std::nullopt;
  }
  return CorruptionDetectionMessage::Builder()
      .WithSequenceIndex(GetSequenceIndexForMessage(
          data.sequence_index, data.communicate_upper_bits))
      .WithInterpretSequenceIndexAsMostSignificantBits(
          data.communicate_upper_bits)
      .WithStdDev(data.std_dev)
      .WithLumaErrorThreshold(data.luma_error_threshold)
      .WithChromaErrorThreshold(data.chroma_error_threshold)
      .WithSampleValues(data.sample_values)
      .Build();
}

std::optional<CorruptionDetectionMessage>
ConvertFrameInstrumentationSyncDataToCorruptionDetectionMessage(
    const FrameInstrumentationSyncData& data) {
  RTC_DCHECK(data.communicate_upper_bits)
      << "FrameInstrumentationSyncData data must always send the upper bits.";

  if (data.sequence_index < 0 || data.sequence_index > 0b0011'1111'1111'1111) {
    return std::nullopt;
  }
  return CorruptionDetectionMessage::Builder()
      .WithSequenceIndex(GetSequenceIndexForMessage(
          data.sequence_index, data.communicate_upper_bits))
      .WithInterpretSequenceIndexAsMostSignificantBits(true)
      .Build();
}

}  // namespace webrtc
