/*
 *  Copyright (c) 2021 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.
 */

#ifndef LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FIELD_ENCODING_PARSER_H_
#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FIELD_ENCODING_PARSER_H_

#include <string>
#include <vector>

#include "absl/strings/string_view.h"
#include "logging/rtc_event_log/events/rtc_event_field_encoding.h"
#include "logging/rtc_event_log/events/rtc_event_log_parse_status.h"

namespace webrtc {

class EventParser {
 public:
  struct ValueAndPostionView {
    rtc::ArrayView<uint64_t> values;
    rtc::ArrayView<uint8_t> positions;
  };

  EventParser() = default;

  // N.B: This method stores a abls::string_view into the string to be
  // parsed. The caller is responsible for ensuring that the actual string
  // remains unmodified and outlives the EventParser.
  RtcEventLogParseStatus Initialize(absl::string_view s, bool batched);

  // Attempts to parse the field specified by `params`, skipping past
  // other fields that may occur before it. If 'required_field == true',
  // then failing to find the field is an error, otherwise the functions
  // return success, but with an empty view of values.
  RtcEventLogParseStatusOr<rtc::ArrayView<absl::string_view>> ParseStringField(
      const FieldParameters& params,
      bool required_field = true);
  RtcEventLogParseStatusOr<rtc::ArrayView<uint64_t>> ParseNumericField(
      const FieldParameters& params,
      bool required_field = true);
  RtcEventLogParseStatusOr<ValueAndPostionView> ParseOptionalNumericField(
      const FieldParameters& params,
      bool required_field = true);

  // Number of events in a batch.
  uint64_t NumEventsInBatch() const { return num_events_; }

  // Bytes remaining in `pending_data_`. Assuming there are no unknown
  // fields, BytesRemaining() should return 0 when all known fields
  // in the event have been parsed.
  size_t RemainingBytes() const { return pending_data_.size(); }

 private:
  uint64_t ReadLittleEndian(uint8_t bytes);
  uint64_t ReadVarInt();
  uint64_t ReadSingleValue(FieldType field_type);
  uint64_t ReadOptionalValuePositions();
  void ReadDeltasAndPopulateValues(FixedLengthEncodingParametersV3 params,
                                   uint64_t num_deltas,
                                   uint64_t base);
  RtcEventLogParseStatus ParseNumericFieldInternal(uint64_t value_bit_width,
                                                   FieldType field_type);
  RtcEventLogParseStatus ParseStringFieldInternal();

  // Attempts to parse the field specified by `params`, skipping past
  // other fields that may occur before it. Returns
  // RtcEventLogParseStatus::Success() and populates `values_` (and
  // `positions_`) if the field is found. Returns
  // RtcEventLogParseStatus::Success() and clears `values_` (and `positions_`)
  // if the field doesn't exist. Returns a RtcEventLogParseStatus::Error() if
  // the log is incomplete, malformed or otherwise can't be parsed.
  RtcEventLogParseStatus ParseField(const FieldParameters& params);

  void SetError() { error_ = true; }
  bool Ok() const { return !error_; }

  rtc::ArrayView<uint64_t> GetValues() { return values_; }
  rtc::ArrayView<uint8_t> GetPositions() { return positions_; }
  rtc::ArrayView<absl::string_view> GetStrings() { return strings_; }

  void ClearTemporaries() {
    positions_.clear();
    values_.clear();
    strings_.clear();
  }

  // Tracks whether an error has occurred in one of the helper
  // functions above.
  bool error_ = false;

  // Temporary storage for result.
  std::vector<uint8_t> positions_;
  std::vector<uint64_t> values_;
  std::vector<absl::string_view> strings_;

  // String to be consumed.
  absl::string_view pending_data_;
  uint64_t num_events_ = 1;
  uint64_t last_field_id_ = FieldParameters::kTimestampField;
};

// Inverse of the ExtractRtcEventMember function used when parsing
// a log. Uses a vector of values to populate a specific field in a
// vector of structs.
template <typename T,
          typename E,
          std::enable_if_t<std::is_integral<T>::value, bool> = true>
ABSL_MUST_USE_RESULT RtcEventLogParseStatus
PopulateRtcEventMember(const rtc::ArrayView<uint64_t> values,
                       T E::*member,
                       rtc::ArrayView<E> output) {
  size_t batch_size = values.size();
  RTC_CHECK_EQ(output.size(), batch_size);
  for (size_t i = 0; i < batch_size; ++i) {
    output[i].*member = DecodeFromUnsignedToType<T>(values[i]);
  }
  return RtcEventLogParseStatus::Success();
}

// Same as above, but for optional fields.
template <typename T,
          typename E,
          std::enable_if_t<std::is_integral<T>::value, bool> = true>
ABSL_MUST_USE_RESULT RtcEventLogParseStatus
PopulateRtcEventMember(const rtc::ArrayView<uint8_t> positions,
                       const rtc::ArrayView<uint64_t> values,
                       absl::optional<T> E::*member,
                       rtc::ArrayView<E> output) {
  size_t batch_size = positions.size();
  RTC_CHECK_EQ(output.size(), batch_size);
  RTC_CHECK_LE(values.size(), batch_size);
  auto value_it = values.begin();
  for (size_t i = 0; i < batch_size; ++i) {
    if (positions[i]) {
      RTC_CHECK(value_it != values.end());
      output[i].*member = DecodeFromUnsignedToType<T>(value_it);
      ++value_it;
    } else {
      output[i].*member = absl::nullopt;
    }
  }
  RTC_CHECK(value_it == values.end());
  return RtcEventLogParseStatus::Success();
}

// Same as above, but for enum fields.
template <typename T,
          typename E,
          std::enable_if_t<std::is_enum<T>::value, bool> = true>
ABSL_MUST_USE_RESULT RtcEventLogParseStatus
PopulateRtcEventMember(const rtc::ArrayView<uint64_t> values,
                       T E::*member,
                       rtc::ArrayView<E> output) {
  size_t batch_size = values.size();
  RTC_CHECK_EQ(output.size(), batch_size);
  for (size_t i = 0; i < batch_size; ++i) {
    auto result = RtcEventLogEnum<T>::Decode(values[i]);
    if (!result.ok()) {
      return result.status();
    }
    output[i].*member = result.value();
  }
  return RtcEventLogParseStatus::Success();
}

// Same as above, but for string fields.
template <typename E>
ABSL_MUST_USE_RESULT RtcEventLogParseStatus
PopulateRtcEventMember(const rtc::ArrayView<absl::string_view> values,
                       std::string E::*member,
                       rtc::ArrayView<E> output) {
  size_t batch_size = values.size();
  RTC_CHECK_EQ(output.size(), batch_size);
  for (size_t i = 0; i < batch_size; ++i) {
    output[i].*member = values[i];
  }
  return RtcEventLogParseStatus::Success();
}

// Same as above, but for Timestamp fields.
// N.B. Assumes that the encoded value uses millisecond precision.
template <typename E>
ABSL_MUST_USE_RESULT RtcEventLogParseStatus
PopulateRtcEventTimestamp(const rtc::ArrayView<uint64_t>& values,
                          Timestamp E::*timestamp,
                          rtc::ArrayView<E> output) {
  size_t batch_size = values.size();
  RTC_CHECK_EQ(batch_size, output.size());
  for (size_t i = 0; i < batch_size; ++i) {
    output[i].*timestamp =
        Timestamp::Millis(DecodeFromUnsignedToType<int64_t>(values[i]));
  }
  return RtcEventLogParseStatus::Success();
}

template <typename E>
rtc::ArrayView<E> ExtendLoggedBatch(std::vector<E>& output,
                                    size_t new_elements) {
  size_t old_size = output.size();
  output.insert(output.end(), old_size + new_elements, E());
  rtc::ArrayView<E> output_batch = output;
  output_batch.subview(old_size);
  RTC_DCHECK_EQ(output_batch.size(), new_elements);
  return output_batch;
}

}  // namespace webrtc
#endif  // LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FIELD_ENCODING_PARSER_H_
