// Copyright 2015 Google Inc. 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/storage/virtual_file_system.h"

#include "base/logging.h"
#include "base/synchronization/lock.h"
#include "cobalt/storage/virtual_file.h"

#include "starboard/client_porting/poem/string_poem.h"

namespace cobalt {
namespace storage {

namespace {
// Update this any time the serialization format changes.
const char kVersion[] = "SAV0";
}  // namespace

// static
int VirtualFileSystem::GetHeaderVersion(const SerializedHeader& header) {
  // Copy the version int to a char buffer to avoid endian issues.
  char version[4];
  memcpy(version, &header.version, sizeof(version));

  if (memcmp(version, kVersion, 3) != 0) {
    return -1;
  } else if (header.file_size < static_cast<int>(sizeof(SerializedHeader))) {
    return -1;
  } else {
    return version[3] - '0';
  }
}

// static
int VirtualFileSystem::GetCurrentVersion() {
  COMPILE_ASSERT(sizeof(kVersion) - 1 == 4, Unexpected_version_size);
  int version;
  memcpy(&version, kVersion, sizeof(version));
  return version;
}

VirtualFileSystem::VirtualFileSystem() {}

VirtualFileSystem::~VirtualFileSystem() {
  DCHECK(thread_checker_.CalledOnValidThread());
  base::AutoLock lock(file_table_lock_);
  ClearFileTable();
}

VirtualFile* VirtualFileSystem::Open(const std::string& filename) {
  base::AutoLock lock(file_table_lock_);
  VirtualFile* result = NULL;
  FileTable::iterator it = table_.find(filename);
  if (it != table_.end()) {
    result = it->second;
  } else {
    result = new VirtualFile(filename);
    table_.insert(it, FileTable::value_type(filename, result));
  }
  return result;
}

std::vector<std::string> VirtualFileSystem::ListFiles() {
  base::AutoLock lock(file_table_lock_);
  std::vector<std::string> files;
  for (FileTable::iterator it = table_.begin(); it != table_.end(); ++it) {
    files.push_back(it->first);
  }
  return files;
}

void VirtualFileSystem::Delete(const std::string& filename) {
  base::AutoLock lock(file_table_lock_);
  FileTable::iterator it = table_.find(filename);
  if (it != table_.end()) {
    delete it->second;
    table_.erase(it);
  }
}

int VirtualFileSystem::Serialize(uint8* buffer, bool dry_run) {
  DCHECK(thread_checker_.CalledOnValidThread());
  base::AutoLock lock(file_table_lock_);
  uint8* original = buffer;

  // We don't know the total size of the file yet, so defer writing the header.
  buffer += sizeof(SerializedHeader);
  int valid_file_count = 0;

  // Serialize each file
  for (FileTable::iterator it = table_.begin(); it != table_.end(); ++it) {
    if (it->second->Size() == 0) {
      continue;
    }
    int file_bytes = it->second->Serialize(buffer, dry_run);
    buffer += file_bytes;
    valid_file_count++;
  }
  const int bytes_written = static_cast<int>(buffer - original);
  if (!dry_run) {
    // Now we can write the header to the beginning of the buffer.
    SerializedHeader header;
    header.version = GetCurrentVersion();
    header.file_count = valid_file_count;
    header.file_size = bytes_written;
    memcpy(original, &header, sizeof(SerializedHeader));
  }

  return bytes_written;
}

bool VirtualFileSystem::Deserialize(const uint8* buffer, int buffer_size_in) {
  const uint8* caller_buffer = buffer;

  base::AutoLock lock(file_table_lock_);
  ClearFileTable();

  if (buffer_size_in < 0) {
    DLOG(ERROR) << "Buffer size must be positive: " << buffer_size_in
                << " < 0.";
    return false;
  }

  size_t buffer_size = static_cast<size_t>(buffer_size_in);

  // The size of the buffer must be checked before copying the beginning of it
  // into a SerializedHeader.
  if (buffer_size < sizeof(SerializedHeader)) {
    DLOG(ERROR) << "Buffer size " << buffer_size
                << " is too small to contain a SerializedHeader of size "
                << sizeof(SerializedHeader) << "; operation aborted.";
    return false;
  }

  // Read in expected number of files
  SerializedHeader header;
  memcpy(&header, buffer, sizeof(SerializedHeader));
  buffer += sizeof(SerializedHeader);

  int buffer_version = GetHeaderVersion(header);
  if (buffer_version != 0) {
    // Note: We would handle old versions here, if necessary.
    DLOG(ERROR) << "Attempted to load a different version; operation aborted.";
    return false;
  } else if (static_cast<size_t>(header.file_size) != buffer_size) {
    DLOG(ERROR) << "Buffer size mismatch: " << header.file_size
                << " != " << buffer_size;
    return false;
  }

  for (int i = 0; i < header.file_count; ++i) {
    size_t buffer_used = static_cast<size_t>(buffer - caller_buffer);
    if (buffer_size < buffer_used) {
      DLOG(ERROR) << "Buffer overrun deserializing files";
      ClearFileTable();
      return false;
    }
    size_t buffer_remaining = buffer_size - buffer_used;

    VirtualFile* file = new VirtualFile("");

    int bytes = file->Deserialize(buffer, buffer_remaining);
    if (bytes > 0) {
      buffer += bytes;
      table_[file->name_] = file;
    } else {
      DLOG(WARNING) << "Failed to deserialize virtual file system.";
      delete file;
      ClearFileTable();
      return false;
    }
  }
  return true;
}

void VirtualFileSystem::ClearFileTable() {
  DCHECK(thread_checker_.CalledOnValidThread());
  file_table_lock_.AssertAcquired();
  for (FileTable::iterator it = table_.begin(); it != table_.end(); ++it) {
    delete it->second;
  }
  table_.clear();
}

}  // namespace storage
}  // namespace cobalt
