// Copyright 2022 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/cache/memory_capped_directory.h"

#include <algorithm>

#include "base/files/file_util.h"
#include "base/strings/string_number_conversions.h"
#include "starboard/directory.h"

namespace cobalt {
namespace cache {

MemoryCappedDirectory::FileInfo::FileInfo(
    base::FilePath directory_path, base::FileEnumerator::FileInfo file_info)
    : file_path_(directory_path.Append(file_info.GetName())),
      last_modified_time_(file_info.GetLastModifiedTime()),
      size_(static_cast<uint32_t>(file_info.GetSize())) {}

MemoryCappedDirectory::FileInfo::FileInfo(base::FilePath file_path,
                                          base::Time last_modified_time,
                                          uint32_t size)
    : file_path_(file_path),
      last_modified_time_(last_modified_time),
      size_(size) {}

bool MemoryCappedDirectory::FileInfo::OldestFirst::operator()(
    const MemoryCappedDirectory::FileInfo& left,
    const MemoryCappedDirectory::FileInfo& right) const {
  return left.last_modified_time_ > right.last_modified_time_;
}

// static
std::unique_ptr<MemoryCappedDirectory> MemoryCappedDirectory::Create(
    const base::FilePath& directory_path, uint32_t max_size) {
  if (!SbDirectoryCreate(directory_path.value().c_str())) {
    return nullptr;
  }
  auto memory_capped_directory = std::unique_ptr<MemoryCappedDirectory>(
      new MemoryCappedDirectory(directory_path, max_size));
  auto* heap = &memory_capped_directory->file_info_heap_;
  base::AutoLock auto_lock(memory_capped_directory->lock_);
  base::FileEnumerator file_enumerator(directory_path, false,
                                       base::FileEnumerator::FILES);
  uint32_t size = 0u;
  while (!file_enumerator.Next().empty()) {
    MemoryCappedDirectory::FileInfo file_info(directory_path,
                                              file_enumerator.GetInfo());
    heap->push_back(file_info);
    memory_capped_directory->file_sizes_[file_info.file_path_] =
        file_info.size_;
    memory_capped_directory->size_ += file_info.size_;
  }
  if (heap->size() > 1) {
    std::make_heap(heap->begin(), heap->end(),
                   MemoryCappedDirectory::FileInfo::OldestFirst());
  }
  return memory_capped_directory;
}

void MemoryCappedDirectory::Delete(uint32_t key) {
  base::AutoLock auto_lock(lock_);
  auto file_path = GetFilePath(key);
  if (base::PathExists(file_path)) {
    base::DeleteFile(file_path, false);
  }
  file_sizes_.erase(file_path);
  auto* heap = &file_info_heap_;
  for (auto it = heap->begin(); it != heap->end(); ++it) {
    if (it->file_path_ == file_path) {
      size_ -= it->size_;
      heap->erase(it);
      if (heap->size() > 1) {
        std::make_heap(heap->begin(), heap->end(),
                       MemoryCappedDirectory::FileInfo::OldestFirst());
      }
      return;
    }
  }
}

std::unique_ptr<std::vector<uint8_t>> MemoryCappedDirectory::Retrieve(
    uint32_t key) {
  auto file_path = GetFilePath(key);
  auto it = file_sizes_.find(file_path);
  if (it == file_sizes_.end()) {
    return nullptr;
  }
  auto size = it->second;
  auto data = std::make_unique<std::vector<uint8_t>>(static_cast<size_t>(size));
  int bytes_read = base::ReadFile(
      file_path, reinterpret_cast<char*>(data->data()), static_cast<int>(size));
  if (bytes_read != size) {
    return nullptr;
  }
  return data;
}

void MemoryCappedDirectory::Store(uint32_t key,
                                  const std::vector<uint8_t>& data) {
  base::AutoLock auto_lock(lock_);
  auto file_path = GetFilePath(key);
  uint32_t new_entry_size = static_cast<uint32_t>(data.size());
  if (!EnsureEnoughSpace(new_entry_size)) {
    return;
  }
  int bytes_written = base::WriteFile(
      file_path, reinterpret_cast<const char*>(data.data()), data.size());
  if (bytes_written != data.size()) {
    base::DeleteFile(file_path, false);
    return;
  }
  size_ += new_entry_size;
  auto* heap = &file_info_heap_;
  heap->push_back(MemoryCappedDirectory::FileInfo(file_path, base::Time::Now(),
                                                  new_entry_size));
  std::push_heap(heap->begin(), heap->end(),
                 MemoryCappedDirectory::FileInfo::OldestFirst());
  file_sizes_[file_path] = new_entry_size;
}

MemoryCappedDirectory::MemoryCappedDirectory(
    const base::FilePath& directory_path, uint32_t max_size)
    : directory_path_(directory_path), max_size_(max_size), size_(0u) {}

base::FilePath MemoryCappedDirectory::GetFilePath(uint32_t key) const {
  return directory_path_.Append(base::UintToString(key));
}

bool MemoryCappedDirectory::EnsureEnoughSpace(
    uint32_t additional_size_required) {
  if (additional_size_required > max_size_) {
    return false;
  }
  auto* heap = &file_info_heap_;
  while (size_ + additional_size_required > max_size_) {
    if (heap->size() == 0) {
      return false;
    }
    std::pop_heap(heap->begin(), heap->end(),
                  MemoryCappedDirectory::FileInfo::OldestFirst());
    auto removed = heap->back();
    size_ -= removed.size_;
    base::DeleteFile(removed.file_path_, false);
    file_sizes_.erase(removed.file_path_);
    heap->pop_back();
  }
  return true;
}

}  // namespace cache
}  // namespace cobalt
