/*
 *  Copyright 2015 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 "rtc_base/filerotatingstream.h"

#include <algorithm>
#include <cstdio>
#include <string>

#include "rtc_base/checks.h"
#include "rtc_base/fileutils.h"
#include "rtc_base/pathutils.h"
#include "rtc_base/strings/string_builder.h"

// Note: We use fprintf for logging in the write paths of this stream to avoid
// infinite loops when logging.

namespace rtc {

FileRotatingStream::FileRotatingStream(const std::string& dir_path,
                                       const std::string& file_prefix)
    : FileRotatingStream(dir_path, file_prefix, 0, 0, kRead) {
}

FileRotatingStream::FileRotatingStream(const std::string& dir_path,
                                       const std::string& file_prefix,
                                       size_t max_file_size,
                                       size_t num_files)
    : FileRotatingStream(dir_path,
                         file_prefix,
                         max_file_size,
                         num_files,
                         kWrite) {
  RTC_DCHECK_GT(max_file_size, 0);
  RTC_DCHECK_GT(num_files, 1);
}

FileRotatingStream::FileRotatingStream(const std::string& dir_path,
                                       const std::string& file_prefix,
                                       size_t max_file_size,
                                       size_t num_files,
                                       Mode mode)
    : dir_path_(dir_path),
      file_prefix_(file_prefix),
      mode_(mode),
      file_stream_(nullptr),
      max_file_size_(max_file_size),
      current_file_index_(0),
      rotation_index_(0),
      current_bytes_written_(0),
      disable_buffering_(false) {
  RTC_DCHECK(Filesystem::IsFolder(dir_path));
  switch (mode) {
    case kWrite: {
      file_names_.clear();
      for (size_t i = 0; i < num_files; ++i) {
        file_names_.push_back(GetFilePath(i, num_files));
      }
      rotation_index_ = num_files - 1;
      break;
    }
    case kRead: {
      file_names_ = GetFilesWithPrefix();
      std::sort(file_names_.begin(), file_names_.end());
      if (file_names_.size() > 0) {
        // |file_names_| is sorted newest first, so read from the end.
        current_file_index_ = file_names_.size() - 1;
      }
      break;
    }
  }
}

FileRotatingStream::~FileRotatingStream() {
}

StreamState FileRotatingStream::GetState() const {
  if (mode_ == kRead && current_file_index_ < file_names_.size()) {
    return SS_OPEN;
  }
  if (!file_stream_) {
    return SS_CLOSED;
  }
  return file_stream_->GetState();
}

StreamResult FileRotatingStream::Read(void* buffer,
                                      size_t buffer_len,
                                      size_t* read,
                                      int* error) {
  RTC_DCHECK(buffer);
  if (mode_ != kRead) {
    return SR_EOS;
  }
  if (current_file_index_ >= file_names_.size()) {
    return SR_EOS;
  }
  // We will have no file stream initially, and when we are finished with the
  // previous file.
  if (!file_stream_) {
    if (!OpenCurrentFile()) {
      return SR_ERROR;
    }
  }
  int local_error = 0;
  if (!error) {
    error = &local_error;
  }
  StreamResult result = file_stream_->Read(buffer, buffer_len, read, error);
  if (result == SR_EOS || result == SR_ERROR) {
    if (result == SR_ERROR) {
      RTC_LOG(LS_ERROR) << "Failed to read from: "
                        << file_names_[current_file_index_]
                        << "Error: " << error;
    }
    // Reached the end of the file, read next file. If there is an error return
    // the error status but allow for a next read by reading next file.
    CloseCurrentFile();
    if (current_file_index_ == 0) {
      // Just finished reading the last file, signal EOS by setting index.
      current_file_index_ = file_names_.size();
    } else {
      --current_file_index_;
    }
    if (read) {
      *read = 0;
    }
    return result == SR_EOS ? SR_SUCCESS : result;
  } else if (result == SR_SUCCESS) {
    // Succeeded, continue reading from this file.
    return SR_SUCCESS;
  } else {
    RTC_NOTREACHED();
  }
  return result;
}

StreamResult FileRotatingStream::Write(const void* data,
                                       size_t data_len,
                                       size_t* written,
                                       int* error) {
  if (mode_ != kWrite) {
    return SR_EOS;
  }
  if (!file_stream_) {
    std::fprintf(stderr, "Open() must be called before Write.\n");
    return SR_ERROR;
  }
  // Write as much as will fit in to the current file.
  RTC_DCHECK_LT(current_bytes_written_, max_file_size_);
  size_t remaining_bytes = max_file_size_ - current_bytes_written_;
  size_t write_length = std::min(data_len, remaining_bytes);
  size_t local_written = 0;
  if (!written) {
    written = &local_written;
  }
  StreamResult result = file_stream_->Write(data, write_length, written, error);
  current_bytes_written_ += *written;

  // If we're done with this file, rotate it out.
  if (current_bytes_written_ >= max_file_size_) {
    RTC_DCHECK_EQ(current_bytes_written_, max_file_size_);
    RotateFiles();
  }
  return result;
}

bool FileRotatingStream::Flush() {
  if (!file_stream_) {
    return false;
  }
  return file_stream_->Flush();
}

bool FileRotatingStream::GetSize(size_t* size) const {
  if (mode_ != kRead) {
    // Not possible to get accurate size on disk when writing because of
    // potential buffering.
    return false;
  }
  RTC_DCHECK(size);
  *size = 0;
  size_t total_size = 0;
  for (auto file_name : file_names_) {
    Pathname pathname(file_name);
    size_t file_size = 0;
    if (Filesystem::GetFileSize(file_name, &file_size)) {
      total_size += file_size;
    }
  }
  *size = total_size;
  return true;
}

void FileRotatingStream::Close() {
  CloseCurrentFile();
}

bool FileRotatingStream::Open() {
  switch (mode_) {
    case kRead:
      // Defer opening to when we first read since we want to return read error
      // if we fail to open next file.
      return true;
    case kWrite: {
      // Delete existing files when opening for write.
      std::vector<std::string> matching_files = GetFilesWithPrefix();
      for (auto matching_file : matching_files) {
        if (!Filesystem::DeleteFile(matching_file)) {
          std::fprintf(stderr, "Failed to delete: %s\n", matching_file.c_str());
        }
      }
      return OpenCurrentFile();
    }
  }
  return false;
}

bool FileRotatingStream::DisableBuffering() {
  disable_buffering_ = true;
  if (!file_stream_) {
    std::fprintf(stderr, "Open() must be called before DisableBuffering().\n");
    return false;
  }
  return file_stream_->DisableBuffering();
}

std::string FileRotatingStream::GetFilePath(size_t index) const {
  RTC_DCHECK_LT(index, file_names_.size());
  return file_names_[index];
}

bool FileRotatingStream::OpenCurrentFile() {
  CloseCurrentFile();

  // Opens the appropriate file in the appropriate mode.
  RTC_DCHECK_LT(current_file_index_, file_names_.size());
  std::string file_path = file_names_[current_file_index_];
  file_stream_.reset(new FileStream());
  const char* mode = nullptr;
  switch (mode_) {
    case kWrite:
      mode = "w+";
      // We should always we writing to the zero-th file.
      RTC_DCHECK_EQ(current_file_index_, 0);
      break;
    case kRead:
      mode = "r";
      break;
  }
  int error = 0;
  if (!file_stream_->Open(file_path, mode, &error)) {
    std::fprintf(stderr, "Failed to open: %s Error: %i\n", file_path.c_str(),
                 error);
    file_stream_.reset();
    return false;
  }
  if (disable_buffering_) {
    file_stream_->DisableBuffering();
  }
  return true;
}

void FileRotatingStream::CloseCurrentFile() {
  if (!file_stream_) {
    return;
  }
  current_bytes_written_ = 0;
  file_stream_.reset();
}

void FileRotatingStream::RotateFiles() {
  RTC_DCHECK_EQ(mode_, kWrite);
  CloseCurrentFile();
  // Rotates the files by deleting the file at |rotation_index_|, which is the
  // oldest file and then renaming the newer files to have an incremented index.
  // See header file comments for example.
  RTC_DCHECK_LT(rotation_index_, file_names_.size());
  std::string file_to_delete = file_names_[rotation_index_];
  if (Filesystem::IsFile(file_to_delete)) {
    if (!Filesystem::DeleteFile(file_to_delete)) {
      std::fprintf(stderr, "Failed to delete: %s\n", file_to_delete.c_str());
    }
  }
  for (auto i = rotation_index_; i > 0; --i) {
    std::string rotated_name = file_names_[i];
    std::string unrotated_name = file_names_[i - 1];
    if (Filesystem::IsFile(unrotated_name)) {
      if (!Filesystem::MoveFile(unrotated_name, rotated_name)) {
        std::fprintf(stderr, "Failed to move: %s to %s\n",
                     unrotated_name.c_str(), rotated_name.c_str());
      }
    }
  }
  // Create a new file for 0th index.
  OpenCurrentFile();
  OnRotation();
}

std::vector<std::string> FileRotatingStream::GetFilesWithPrefix() const {
  std::vector<std::string> files;
  // Iterate over the files in the directory.
  DirectoryIterator it;
  Pathname dir_path;
  dir_path.SetFolder(dir_path_);
  if (!it.Iterate(dir_path)) {
    return files;
  }
  do {
    std::string current_name = it.Name();
    if (current_name.size() && !it.IsDirectory() &&
        current_name.compare(0, file_prefix_.size(), file_prefix_) == 0) {
      Pathname path(dir_path_, current_name);
      files.push_back(path.pathname());
    }
  } while (it.Next());
  return files;
}

std::string FileRotatingStream::GetFilePath(size_t index,
                                            size_t num_files) const {
  RTC_DCHECK_LT(index, num_files);

  const size_t buffer_size = 32;
  char file_postfix[buffer_size];
  // We want to zero pad the index so that it will sort nicely.
  const int max_digits = std::snprintf(nullptr, 0, "%zu", num_files - 1);
  RTC_DCHECK_LT(1 + max_digits, buffer_size);
  std::snprintf(file_postfix, buffer_size, "_%0*zu", max_digits, index);

  Pathname file_path(dir_path_, file_prefix_ + file_postfix);
  return file_path.pathname();
}

CallSessionFileRotatingStream::CallSessionFileRotatingStream(
    const std::string& dir_path)
    : FileRotatingStream(dir_path, kLogPrefix),
      max_total_log_size_(0),
      num_rotations_(0) {
}

CallSessionFileRotatingStream::CallSessionFileRotatingStream(
    const std::string& dir_path,
    size_t max_total_log_size)
    : FileRotatingStream(dir_path,
                         kLogPrefix,
                         max_total_log_size / 2,
                         GetNumRotatingLogFiles(max_total_log_size) + 1),
      max_total_log_size_(max_total_log_size),
      num_rotations_(0) {
  RTC_DCHECK_GE(max_total_log_size, 4);
}

const char* CallSessionFileRotatingStream::kLogPrefix = "webrtc_log";
const size_t CallSessionFileRotatingStream::kRotatingLogFileDefaultSize =
    1024 * 1024;

void CallSessionFileRotatingStream::OnRotation() {
  ++num_rotations_;
  if (num_rotations_ == 1) {
    // On the first rotation adjust the max file size so subsequent files after
    // the first are smaller.
    SetMaxFileSize(GetRotatingLogSize(max_total_log_size_));
  } else if (num_rotations_ == (GetNumFiles() - 1)) {
    // On the next rotation the very first file is going to be deleted. Change
    // the rotation index so this doesn't happen.
    SetRotationIndex(GetRotationIndex() - 1);
  }
}

size_t CallSessionFileRotatingStream::GetRotatingLogSize(
    size_t max_total_log_size) {
  size_t num_rotating_log_files = GetNumRotatingLogFiles(max_total_log_size);
  size_t rotating_log_size = num_rotating_log_files > 2
                                 ? kRotatingLogFileDefaultSize
                                 : max_total_log_size / 4;
  return rotating_log_size;
}

size_t CallSessionFileRotatingStream::GetNumRotatingLogFiles(
    size_t max_total_log_size) {
  // At minimum have two rotating files. Otherwise split the available log size
  // evenly across 1MB files.
  return std::max((size_t)2,
                  (max_total_log_size / 2) / kRotatingLogFileDefaultSize);
}

}  // namespace rtc
