/*
 *  Copyright (c) 2014 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 "test/rtp_file_writer.h"

#include <stdint.h>
#include <stdio.h>

#include <optional>
#include <string>

#include "rtc_base/checks.h"

namespace webrtc {
namespace test {

static const uint16_t kPacketHeaderSize = 8;
static const char kFirstLine[] = "#!rtpplay1.0 0.0.0.0/0\n";

// Write RTP packets to file in rtpdump format, as documented at:
// http://www.cs.columbia.edu/irt/software/rtptools/
class RtpDumpWriter : public RtpFileWriter {
 public:
  explicit RtpDumpWriter(FILE* file) : file_(file) {
    RTC_CHECK(file_ != NULL);
    Init();
  }
  ~RtpDumpWriter() override {
    if (file_ != NULL) {
      fclose(file_);
      file_ = NULL;
    }
  }

  RtpDumpWriter(const RtpDumpWriter&) = delete;
  RtpDumpWriter& operator=(const RtpDumpWriter&) = delete;

  bool WritePacket(const RtpPacket* packet) override {
    if (!first_packet_time_) {
      first_packet_time_ = packet->time_ms;
    }
    uint16_t len = static_cast<uint16_t>(packet->length + kPacketHeaderSize);
    uint16_t plen = static_cast<uint16_t>(packet->original_length);
    uint32_t offset = packet->time_ms - *first_packet_time_;
    RTC_CHECK(WriteUint16(len));
    RTC_CHECK(WriteUint16(plen));
    RTC_CHECK(WriteUint32(offset));
    return fwrite(packet->data, sizeof(uint8_t), packet->length, file_) ==
           packet->length;
  }

 private:
  bool Init() {
    fprintf(file_, "%s", kFirstLine);

    RTC_CHECK(WriteUint32(0));
    RTC_CHECK(WriteUint32(0));
    RTC_CHECK(WriteUint32(0));
    RTC_CHECK(WriteUint16(0));
    RTC_CHECK(WriteUint16(0));

    return true;
  }

  bool WriteUint32(uint32_t in) {
    // Loop through shifts = {24, 16, 8, 0}.
    for (int shifts = 24; shifts >= 0; shifts -= 8) {
      uint8_t tmp = static_cast<uint8_t>((in >> shifts) & 0xFF);
      if (fwrite(&tmp, sizeof(uint8_t), 1, file_) != 1)
        return false;
    }
    return true;
  }

  bool WriteUint16(uint16_t in) {
    // Write 8 MSBs.
    uint8_t tmp = static_cast<uint8_t>((in >> 8) & 0xFF);
    if (fwrite(&tmp, sizeof(uint8_t), 1, file_) != 1)
      return false;
    // Write 8 LSBs.
    tmp = static_cast<uint8_t>(in & 0xFF);
    if (fwrite(&tmp, sizeof(uint8_t), 1, file_) != 1)
      return false;
    return true;
  }

  FILE* file_;
  std::optional<uint32_t> first_packet_time_;
};

RtpFileWriter* RtpFileWriter::Create(FileFormat format,
                                     const std::string& filename) {
  FILE* file = fopen(filename.c_str(), "wb");
  if (file == NULL) {
    printf("ERROR: Can't open file: %s\n", filename.c_str());
    return NULL;
  }
  switch (format) {
    case kRtpDump:
      return new RtpDumpWriter(file);
  }
  fclose(file);
  return NULL;
}

}  // namespace test
}  // namespace webrtc
