// Copyright 2018 The Fuchsia 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 "raw_video_writer.h"

#include <endian.h>
#include <fcntl.h>
#include <unistd.h>

#include <atomic>
#include <iomanip>
#include <optional>
#include <string>

namespace media {

namespace {

constexpr const char* kDefaultFilePathName = "/tmp/raw_video_writer_";
constexpr const char* kFileExtension = ".raw_video";

}  // namespace

template <>
std::atomic<uint32_t> RawVideoWriter<true>::instance_count_(0u);

template <bool enabled>
RawVideoWriter<enabled>::RawVideoWriter(const char* file_name) {
  if (file_name) {
    file_name_ = file_name;
  } else {
    // mostly a comment
    FX_DCHECK(file_name_.empty());
  }
}

template <bool enabled>
RawVideoWriter<enabled>::~RawVideoWriter() {
  if (!is_done_) {
    Close();
  }
}

template <bool enabled>
bool RawVideoWriter<enabled>::IsOk() {
  return is_ok_;
}

template <bool enabled>
size_t RawVideoWriter<enabled>::WriteUint32BigEndian(uint32_t number) {
  uint32_t to_write = htobe32(number);
  // May Fail() as appropriate.
  WriteData(reinterpret_cast<uint8_t*>(&to_write), sizeof(to_write));
  return sizeof(to_write);
}

template <bool enabled>
size_t RawVideoWriter<enabled>::WriteUint32LittleEndian(uint32_t number) {
  uint32_t to_write = htole32(number);
  // May Fail() as appropriate.
  WriteData(reinterpret_cast<uint8_t*>(&to_write), sizeof(to_write));
  return sizeof(to_write);
}

template <bool enabled>
size_t RawVideoWriter<enabled>::WriteNv12(uint32_t width_pixels, uint32_t height_pixels,
                                          uint32_t stride_bytes, const uint8_t* const y_base,
                                          uint32_t uv_offset) {
  // Despite the copy cost, for now let's perform the write as one big write, to
  // maximize the chance of getting a frame written or not written as a unit in
  // case of concurrent process exit or similar.  The copy cost isn't a huge
  // issue for the intended debugging purpose(s).
  size_t size = height_pixels * width_pixels + height_pixels / 2 * width_pixels;
  if (!y_base) {
    return size;
  }
  if (!uv_offset) {
    uv_offset = height_pixels * stride_bytes;
  }
  // This buffer isn't small.
  std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(size);
  uint8_t* dst = &buffer[0];
  const uint8_t* src = y_base;
  // Y
  for (uint32_t y_line = 0; y_line < height_pixels; y_line++) {
    memcpy(dst, src, width_pixels);
    dst += width_pixels;
    src += stride_bytes;
  }
  // UV
  // dest is already positioned correctly to write UV data.
  // src needs to account for a non-default uv_offset.
  src = y_base + uv_offset;
  for (uint32_t uv_line = 0; uv_line < height_pixels / 2; uv_line++) {
    memcpy(dst, src, width_pixels);
    dst += width_pixels;
    src += stride_bytes;
  }
  WriteData(&buffer[0], size);
  // ~buffer
  return size;
}

// Intentionally don't require IsOk().
template <bool enabled>
void RawVideoWriter<enabled>::Close() {
  // Caller shouldn't call Close() / Delete() repeatedly.
  if (is_done_) {
    Fail();
    return;
  }
  is_done_ = true;

  if (!is_initialized_) {
    // file never created, so nothing to do
    FX_DCHECK(!file_.is_valid());
    return;
  }

  if (!file_.is_valid()) {
    FX_DCHECK(!is_ok_);
    // Don't FX_LOGS(WARNING) again since we already did previously.
    return;
  }
  file_.reset();
  FX_LOGS(INFO) << "Closed raw video file " << std::quoted(file_name_);

  // is_ok_ intentionally not modified
}

// Intentionally don't require IsOk().
template <bool enabled>
void RawVideoWriter<enabled>::Delete() {
  // Caller shouldn't call Close() / Delete() repeatedly.
  if (is_done_) {
    Fail();
    return;
  }
  is_done_ = true;

  if (!is_initialized_) {
    // file never created, so nothing to do
    FX_DCHECK(!file_.is_valid());
    return;
  }

  FX_DCHECK(!file_name_.empty() || !file_.is_valid());
  if (!file_.is_valid()) {
    FX_DCHECK(!is_ok_);
    // Don't FX_LOGS(WARNING) again since we already did previously.
    return;
  }
  file_.reset();

  if (::unlink(file_name_.c_str()) < 0) {
    FX_LOGS(WARNING) << "Could not delete " << std::quoted(file_name_);
    Fail();
    return;
  }

  FX_LOGS(INFO) << "Deleted raw video file " << std::quoted(file_name_);
}

template <bool enabled>
void RawVideoWriter<enabled>::EnsureInitialized() {
  if (!is_initialized_) {
    is_initialized_ = true;
    // If Initialize() actually fails, it's like a write failure later - is_ok_
    // gets set to false.
    Initialize();
  }
}

template <bool enabled>
void RawVideoWriter<enabled>::Initialize() {
  if (file_name_.empty()) {
    uint32_t instance_count = instance_count_.fetch_add(1);
    file_name_ = kDefaultFilePathName;
    file_name_ += std::to_string(instance_count) + kFileExtension;
  }
  file_.reset(::open(file_name_.c_str(), O_CREAT | O_WRONLY | O_TRUNC));
  if (!file_.is_valid()) {
    FX_LOGS(WARNING) << "::open failed for " << std::quoted(file_name_) << ", returned "
                     << file_.get() << ", errno " << errno;
    Fail();
    return;
  }
}

template <bool enabled>
void RawVideoWriter<enabled>::Fail() {
  FX_LOGS(WARNING) << "RawVideoWriter<enabled>::Fail()";
  is_ok_ = false;
  // We intentionally don't Close() or Delete() here - a client can do a Close()
  // or Delete() later without having looked at IsOk(), or might decide whether
  // to Close() or Delete() depending on IsOk()'s value.  The previous ::write()
  // calls should be effective at ensuring the previously written data is
  // preserved should this process exit before a Close() or Delete().
}

template <bool enabled>
void RawVideoWriter<enabled>::WriteData(const uint8_t* to_write, size_t size) {
  EnsureInitialized();
  if (!is_ok_) {
    // Don't FX_LOGS() again because we already did previously.
    return;
  }
  if (is_done_) {
    FX_LOGS(WARNING) << "RawVideoWriter write requested after Close() or Delete()";
    Fail();
    return;
  }
  FX_DCHECK(file_.is_valid());
  ::write(file_.get(), reinterpret_cast<const void*>(to_write), size);
}

template class RawVideoWriter<true>;

}  // namespace media
