// 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.
  auto 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
