/*
 *  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 <utility>

#if defined(WEBRTC_WIN)
#include <windows.h>
#include "rtc_base/stringutils.h"
#else
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#endif  // WEBRTC_WIN

#include "absl/strings/match.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"

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

namespace rtc {

namespace {

std::string AddTrailingPathDelimiterIfNeeded(std::string directory);

// |dir| must have a trailing delimiter. |prefix| must not include wild card
// characters.
std::vector<std::string> GetFilesWithPrefix(const std::string& directory,
                                            const std::string& prefix);
bool DeleteFile(const std::string& file);
bool MoveFile(const std::string& old_file, const std::string& new_file);
bool IsFile(const std::string& file);
bool IsFolder(const std::string& file);
absl::optional<size_t> GetFileSize(const std::string& file);

#if defined(WEBRTC_WIN)

std::string AddTrailingPathDelimiterIfNeeded(std::string directory) {
  if (absl::EndsWith(directory, "\\")) {
    return directory;
  }
  return directory + "\\";
}

std::vector<std::string> GetFilesWithPrefix(const std::string& directory,
                                            const std::string& prefix) {
  RTC_DCHECK(absl::EndsWith(directory, "\\"));
  WIN32_FIND_DATA data;
  HANDLE handle;
  handle = ::FindFirstFile(ToUtf16(directory + prefix + '*').c_str(), &data);
  if (handle == INVALID_HANDLE_VALUE)
    return {};

  std::vector<std::string> file_list;
  do {
    file_list.emplace_back(directory + ToUtf8(data.cFileName));
  } while (::FindNextFile(handle, &data) == TRUE);

  ::FindClose(handle);
  return file_list;
}

bool DeleteFile(const std::string& file) {
  return ::DeleteFile(ToUtf16(file).c_str()) != 0;
}

bool MoveFile(const std::string& old_file, const std::string& new_file) {
  return ::MoveFile(ToUtf16(old_file).c_str(), ToUtf16(new_file).c_str()) != 0;
}

bool IsFile(const std::string& file) {
  WIN32_FILE_ATTRIBUTE_DATA data = {0};
  if (0 == ::GetFileAttributesEx(ToUtf16(file).c_str(), GetFileExInfoStandard,
                                 &data))
    return false;
  return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
}

bool IsFolder(const std::string& file) {
  WIN32_FILE_ATTRIBUTE_DATA data = {0};
  if (0 == ::GetFileAttributesEx(ToUtf16(file).c_str(), GetFileExInfoStandard,
                                 &data))
    return false;
  return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ==
         FILE_ATTRIBUTE_DIRECTORY;
}

absl::optional<size_t> GetFileSize(const std::string& file) {
  WIN32_FILE_ATTRIBUTE_DATA data = {0};
  if (::GetFileAttributesEx(ToUtf16(file).c_str(), GetFileExInfoStandard,
                            &data) == 0)
    return absl::nullopt;
  return data.nFileSizeLow;
}

#else  // defined(WEBRTC_WIN)

std::string AddTrailingPathDelimiterIfNeeded(std::string directory) {
  if (absl::EndsWith(directory, "/")) {
    return directory;
  }
  return directory + "/";
}

std::vector<std::string> GetFilesWithPrefix(const std::string& directory,
                                            const std::string& prefix) {
  RTC_DCHECK(absl::EndsWith(directory, "/"));
  DIR* dir = ::opendir(directory.c_str());
  if (dir == nullptr)
    return {};
  std::vector<std::string> file_list;
  for (struct dirent* dirent = ::readdir(dir); dirent;
       dirent = ::readdir(dir)) {
    std::string name = dirent->d_name;
    if (name.compare(0, prefix.size(), prefix) == 0) {
      file_list.emplace_back(directory + name);
    }
  }
  ::closedir(dir);
  return file_list;
}

bool DeleteFile(const std::string& file) {
  return ::unlink(file.c_str()) == 0;
}

bool MoveFile(const std::string& old_file, const std::string& new_file) {
  return ::rename(old_file.c_str(), new_file.c_str()) == 0;
}

bool IsFile(const std::string& file) {
  struct stat st;
  int res = ::stat(file.c_str(), &st);
  // Treat symlinks, named pipes, etc. all as files.
  return res == 0 && !S_ISDIR(st.st_mode);
}

bool IsFolder(const std::string& file) {
  struct stat st;
  int res = ::stat(file.c_str(), &st);
  return res == 0 && S_ISDIR(st.st_mode);
}

absl::optional<size_t> GetFileSize(const std::string& file) {
  struct stat st;
  if (::stat(file.c_str(), &st) != 0)
    return absl::nullopt;
  return st.st_size;
}

#endif

}  // namespace

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_(AddTrailingPathDelimiterIfNeeded(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(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(dir_path_, file_prefix_);
      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_) {
    total_size += GetFileSize(file_name).value_or(0);
  }
  *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(dir_path_, file_prefix_);
      for (const auto& matching_file : matching_files) {
        if (!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 (IsFile(file_to_delete)) {
    if (!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 (IsFile(unrotated_name)) {
      if (!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::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);

  return dir_path_ + file_prefix_ + file_postfix;
}

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
