// Copyright 2019 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 "starboard/loader_app/installation_manager.h"

#include <sys/stat.h>

#include <set>
#include <string>
#include <vector>

#include "starboard/common/file.h"
#include "starboard/common/log.h"
#include "starboard/common/mutex.h"
#include "starboard/common/scoped_ptr.h"
#include "starboard/common/string.h"
#include "starboard/configuration_constants.h"
#include "starboard/directory.h"
#include "starboard/file.h"
#include "starboard/loader_app/installation_store.pb.h"
#if !SB_IS(EVERGREEN_COMPATIBLE_LITE)
#include "starboard/loader_app/pending_restart.h"  // nogncheck
#endif  // !SB_IS(EVERGREEN_COMPATIBLE_LITE)
#include "starboard/once.h"
#include "starboard/string.h"

namespace starboard {
namespace loader_app {
namespace installation_manager {

class InstallationManager {
 public:
  explicit InstallationManager(int max_num_installations,
                               const std::string& app_key);

  int Initialize();
  int GetAppKey(char* app_key, int app_key_length);
  int GetMaxNumberInstallations();
  int Reset();
  int GetInstallationStatus(int installation_index);
  int GetInstallationNumTriesLeft(int installation_index);
  int RollForwardIfNeeded();
  int RollForward(int installation_index);
  int DecrementInstallationNumTries(int installation_index);

  int RevertToSuccessfulInstallation();
  int GetInstallationPath(int installation_index, char* path, int path_length);
  int GetCurrentInstallationIndex();
  int MarkInstallationSuccessful(int installation_index);
  int SelectNewInstallationIndex();
  int ResetInstallation(int installation_index);
  int RequestRollForwardToInstallation(int installation_index);

 private:
  bool IsValidIndex(int i);
  void ValidatePriorities();
  int FindCurrentInstallationIndex();
  void CreateInstallationStore();
  std::string DumpInstallationSlots();
  void LogLastSystemError(const char* msg);
  void ShiftPrioritiesInRange(int high_priority,
                              int low_priority,
                              int shift_amount);

  int RollForwardInternal(int installation);
  bool InitInstallationStorePath();
  bool LoadInstallationStore();
  bool SaveInstallationStore();
  bool CreateInstallationDirs();
  bool CleanInstallationDirs();
  bool GetInstallationPathInternal(int installation_index,
                                   char* path,
                                   int path_length);

  cobalt::loader::InstallationStore installation_store_;
  bool initialized_;
  int current_installation_;
  std::string app_key_;
  std::string store_path_;
  std::string storage_dir_;
  std::string content_dir_;
  const int max_num_installations_;
  const int lowest_priority_;
  const int highest_priority_;
};

InstallationManager::InstallationManager(int max_num_installations,
                                         const std::string& app_key)
    : initialized_(false),
      current_installation_(-1),
      app_key_(app_key),
      max_num_installations_(max_num_installations),
      lowest_priority_(max_num_installations_ - 1),
      highest_priority_(0) {
  SB_CHECK(max_num_installations_ >= 2);
  SB_CHECK(!app_key.empty());
  SB_LOG(INFO) << "InstallationManager: app_key=" << app_key_;
}

int InstallationManager::Initialize() {
  if (initialized_) {
    return IM_ERROR;
  }
  if (!InitInstallationStorePath()) {
    SB_LOG(ERROR) << "Initialize: failed to init paths";
    return IM_ERROR;
  }

  // If there is no existing store, create one.
  if (!LoadInstallationStore()) {
    CreateInstallationStore();
    current_installation_ = FindCurrentInstallationIndex();
    if (!IsValidIndex(current_installation_)) {
      SB_LOG(ERROR) << "Initialize: Unable to find current installation"
                    << current_installation_;
      return IM_ERROR;
    }
    if (!CreateInstallationDirs()) {
      SB_LOG(ERROR) << "Initialize: Unable to create installations dirs";
      return IM_ERROR;
    }
    initialized_ = SaveInstallationStore();
  } else {
    current_installation_ = FindCurrentInstallationIndex();
    if (!IsValidIndex(current_installation_)) {
      SB_LOG(ERROR) << "Initialize: Unable to find current installation"
                    << current_installation_;
      return IM_ERROR;
    }
    initialized_ = true;
  }
  if (!initialized_) {
    SB_LOG(ERROR) << "Initialize: failed";
  }
  SB_DLOG(INFO) << DumpInstallationSlots();
  return initialized_ ? IM_SUCCESS : IM_ERROR;
}

int InstallationManager::GetAppKey(char* app_key, int app_key_length) {
  SB_LOG(INFO) << "InstallationManager::GetAppKey";
  if (!initialized_) {
    SB_LOG(ERROR) << "GetAppKey: not initialized";
    return IM_ERROR;
  }
  starboard::strlcpy(app_key, app_key_.c_str(), app_key_length);
  return IM_SUCCESS;
}

int InstallationManager::GetMaxNumberInstallations() {
  if (!initialized_) {
    SB_LOG(ERROR) << "GetMaxNumberInstallations: not initialized";
    return IM_ERROR;
  }
  return max_num_installations_;
}

int InstallationManager::Reset() {
  CreateInstallationStore();
  current_installation_ = FindCurrentInstallationIndex();
  if (!IsValidIndex(current_installation_)) {
    SB_LOG(ERROR) << "Reset: Unable to find current installation"
                  << current_installation_;
    return IM_ERROR;
  }
  if (!CleanInstallationDirs()) {
    SB_LOG(ERROR) << "Reset: Unable to clean installations dirs";
    return IM_ERROR;
  }
  if (!SaveInstallationStore()) {
    return IM_ERROR;
  }
  return IM_SUCCESS;
}

void InstallationManager::CreateInstallationStore() {
  installation_store_ = cobalt::loader::InstallationStore();
  int priority = highest_priority_;
  for (int i = 0; i < max_num_installations_; i++) {
    installation_store_.add_installations();
    installation_store_.mutable_installations(i)->set_is_successful(false);
    installation_store_.mutable_installations(i)->set_num_tries_left(
        IM_MAX_NUM_TRIES);
    installation_store_.mutable_installations(i)->set_priority(priority++);
  }
  installation_store_.set_roll_forward_to_installation(-1);
  // Mark the system image as successful.
  installation_store_.mutable_installations(0)->set_is_successful(true);
}

std::string InstallationManager::DumpInstallationSlots() {
  std::ostringstream out;
  out << "size=";
  const int kBufSize = 50;
  char buf_num[kBufSize];
  snprintf(buf_num, kBufSize, "%d", installation_store_.installations_size());
  out << buf_num;

  out << " roll_forward_to_installation=";
  snprintf(buf_num, kBufSize, "%d",
           installation_store_.roll_forward_to_installation());
  out << buf_num;
  out << ";";
  for (int i = 0; i < installation_store_.installations_size(); i++) {
    out << " installation_";
    snprintf(buf_num, kBufSize, "%d", i);
    out << buf_num;
    out << " is_successful=";
    if (installation_store_.installations(i).is_successful()) {
      out << "true";
    } else {
      out << "false";
    }

    out << " num_tries_left=";
    snprintf(buf_num, kBufSize, "%d",
             installation_store_.installations(i).num_tries_left());
    out << buf_num;

    out << " priority=";
    snprintf(buf_num, kBufSize, "%d",
             installation_store_.installations(i).priority());
    out << buf_num;
    out << ";";
  }
  return out.str();
}

int InstallationManager::GetInstallationStatus(int installation_index) {
  if (!initialized_) {
    SB_LOG(ERROR) << "GetInstallationStatus: not initialized";
    return IM_INSTALLATION_STATUS_ERROR;
  }
  if (!IsValidIndex(installation_index)) {
    SB_LOG(ERROR) << "GetInstallationStatus: invalid index: "
                  << installation_index;
    return IM_INSTALLATION_STATUS_ERROR;
  }
  return installation_store_.installations(installation_index).is_successful();
}

int InstallationManager::GetInstallationNumTriesLeft(int installation_index) {
  if (!initialized_) {
    SB_LOG(ERROR) << "GetInstallationNumTriesLeft: not initialized";
    return IM_ERROR;
  }

  if (!IsValidIndex(installation_index)) {
    SB_LOG(ERROR) << "GetInstallationNumTriesLeft: invalid index: "
                  << installation_index;
    return IM_ERROR;
  }
  return installation_store_.installations(installation_index).num_tries_left();
}

int InstallationManager::DecrementInstallationNumTries(int installation_index) {
  if (!initialized_) {
    SB_LOG(ERROR) << "DecrementInstallationNumTries: not initialized";
    return IM_ERROR;
  }
  if (!IsValidIndex(installation_index)) {
    SB_LOG(ERROR) << "DecrementInstallationNumTries: invalid index: "
                  << installation_index;
    return IM_ERROR;
  }

  int num_tries_left =
      installation_store_.installations(installation_index).num_tries_left();
  if (num_tries_left <= 0) {
    return IM_ERROR;
  }
  installation_store_.mutable_installations(installation_index)
      ->set_num_tries_left(--num_tries_left);

  if (!SaveInstallationStore()) {
    SB_LOG(ERROR) << "DecrementInstallationNumTries: failed to save store";
    return IM_ERROR;
  }
  return IM_SUCCESS;
}

//
// Revert to a previous successful installation and make it
// the highest priority. The current installation becomes the
// lowest priority.
//
//     high [-]    [x]
//          [ ]    [ ]
//          [x] => [ ]
//     low  [ ]    [-]
//
int InstallationManager::RevertToSuccessfulInstallation() {
  if (!initialized_) {
    SB_LOG(ERROR) << "RevertToSuccessfulInstallation: not initialized";
    return IM_ERROR;
  }
  int fallback_priority = lowest_priority_;
  int fallback_installation = -1;

  SB_DLOG(INFO) << "RevertToSuccessfulInstallation: Start "
                << DumpInstallationSlots();
  // Find the highest priority successful installation for fallback.
  for (int i = 0; i < installation_store_.installations().size(); i++) {
    int priority = installation_store_.installations(i).priority();
    if (installation_store_.installations(i).is_successful() &&
        priority > highest_priority_ && priority <= fallback_priority) {
      fallback_priority = priority;
      fallback_installation = i;
      SB_DLOG(INFO) << "fallback_installation= " << fallback_installation;
    }
  }

  if (fallback_installation == -1) {
    SB_LOG(ERROR) << "RevertToSuccessfulInstallation: Unable to find fallback "
                     "installation";
    return IM_ERROR;
  }

  // Shift up all the priorities below the fallback installation up.
  ShiftPrioritiesInRange(fallback_priority, lowest_priority_,
                         -1 /* shift up -1 */);

  // Disable current installation.
  installation_store_.mutable_installations(current_installation_)
      ->set_priority(lowest_priority_);

  // Move the current installation at the bottom.
  installation_store_.mutable_installations(current_installation_)
      ->set_is_successful(false);

  // Change current installation.
  installation_store_.mutable_installations(fallback_installation)
      ->set_priority(highest_priority_);
  current_installation_ = fallback_installation;

  SB_DLOG(INFO) << "RevertToSuccessfulInstallation: End "
                << DumpInstallationSlots();

  if (SaveInstallationStore()) {
    return fallback_installation;
  }
  return IM_ERROR;
}

int InstallationManager::RollForward(int installation_index) {
  if (!initialized_) {
    SB_LOG(ERROR) << "RollForward: not initialized";
    return IM_ERROR;
  }

  if (!IsValidIndex(installation_index)) {
    SB_LOG(ERROR) << "RollForward: invalid installation=" << installation_index;
    return IM_ERROR;
  }
  SB_DLOG(INFO) << "RollForward: installation=" << installation_index;

  return RollForwardInternal(installation_index);
}

int InstallationManager::RollForwardIfNeeded() {
  if (!initialized_) {
    SB_LOG(ERROR) << "RollForwardIfNeeded: not initialized";
    return IM_ERROR;
  }
  //  Check if we need to roll_forward to new slot.
  int new_installation = installation_store_.roll_forward_to_installation();
  if (new_installation == -1) {
    // No need to roll forward.
    return IM_SUCCESS;
  }
  if (!IsValidIndex(new_installation)) {
    SB_LOG(ERROR) << "RollForwardIfNeeded: invalid new_installation="
                  << new_installation;
    return IM_ERROR;
  }
  SB_DLOG(INFO) << "RollForwardIfNeeded: new_installation=" << new_installation;

  return RollForwardInternal(new_installation);
}

//
// Roll forward to a new installation and make it
// the new highest priority installation.
//
//     high [ ]    [x]
//          [ ]    [ ]
//          [x] => [ ]
//     low  [ ]    [ ]
//
int InstallationManager::RollForwardInternal(int installation_index) {
  // Save old priority.
  int new_installation_old_priority =
      installation_store_.installations(installation_index).priority();

  SB_DLOG(INFO) << "RollForwardInternal: new_installation_old_priority="
                << new_installation_old_priority;

  // Lower priorities of all jumped over installations.
  ShiftPrioritiesInRange(highest_priority_, new_installation_old_priority,
                         1 /* shift down +1 */);

  // The new installation will be set to the highest priority.
  installation_store_.mutable_installations(installation_index)
      ->set_priority(highest_priority_);

  // Reset the roll forward index.
  installation_store_.set_roll_forward_to_installation(-1);
  current_installation_ = installation_index;

  SB_DLOG(INFO) << "RollForwardInternal: " << DumpInstallationSlots();
  return SaveInstallationStore() ? IM_SUCCESS : IM_ERROR;
}

// Shift the priority in the inclusive range either up or down based
// on the |direction_up" flag.
void InstallationManager::ShiftPrioritiesInRange(int high_priority,
                                                 int low_priority,
                                                 int shift_amount) {
  for (int i = 0; i < installation_store_.installations().size(); i++) {
    int priority = installation_store_.installations(i).priority();
    if (priority >= high_priority && priority <= low_priority) {
      installation_store_.mutable_installations(i)->set_priority(priority +
                                                                 shift_amount);
      SB_DLOG(INFO) << "ShiftPrioritiesInRange i=" << i
                    << " priority_new=" << priority;
    }
  }
}

int InstallationManager::GetInstallationPath(int installation_index,
                                             char* path,
                                             int path_length) {
  if (!initialized_) {
    SB_LOG(ERROR) << "GetInstallationPath: not initialized";
    return IM_ERROR;
  }
  return GetInstallationPathInternal(installation_index, path, path_length)
             ? IM_SUCCESS
             : IM_ERROR;
}

int InstallationManager::GetCurrentInstallationIndex() {
  if (!initialized_) {
    SB_LOG(ERROR) << "GetCurrentInstallationIndex: not initialized";
    return IM_ERROR;
  }
  return current_installation_;
}

void InstallationManager::LogLastSystemError(const char* msg) {
  const int kErrorMessageBufferSize = 256;
  char msgbuf[kErrorMessageBufferSize];
  SbSystemError error_code = SbSystemGetLastError();
  if (SbSystemGetErrorString(error_code, msgbuf, kErrorMessageBufferSize) > 0) {
    SB_LOG(ERROR) << msg << ": " << msgbuf;
  }
}

int InstallationManager::FindCurrentInstallationIndex() {
  int highest_priority_index = -1;
  for (int i = 0; i < installation_store_.installations_size(); i++) {
    if (highest_priority_ == installation_store_.installations(i).priority()) {
      highest_priority_index = i;
      break;
    }
  }

  return highest_priority_index;
}

int InstallationManager::MarkInstallationSuccessful(int installation_index) {
  if (!initialized_) {
    SB_LOG(ERROR) << "MarkInstallationSuccessful: not initialized";
    return IM_ERROR;
  }
  if (!IsValidIndex(installation_index)) {
    SB_LOG(ERROR) << "MarkInstallationSuccessful: invalid index"
                  << installation_index;
    return IM_ERROR;
  }
  if (!installation_store_.installations(installation_index).is_successful()) {
    installation_store_.mutable_installations(installation_index)
        ->set_is_successful(true);
    return SaveInstallationStore() ? IM_SUCCESS : IM_ERROR;
  }
  return IM_SUCCESS;
}

int InstallationManager::SelectNewInstallationIndex() {
  if (!initialized_) {
    SB_LOG(ERROR) << "SelectNewInstallationIndex: not initialized";
    return IM_ERROR;
  }

  int priority = highest_priority_;
  int new_installation_index = -1;

  // SLOT_0 is placed in |kSbSystemPathContentDirectory|, under the subdirectory
  // 'app/cobalt', and is always the system image.
  int start = 1;

  // Find the lowest priority installation that we can use.
  for (int i = start; i < installation_store_.installations().size(); i++) {
    if (priority < installation_store_.installations(i).priority()) {
      new_installation_index = i;
      priority = installation_store_.installations(i).priority();
      SB_DLOG(INFO) << "SelectNewInstallationIndex: lowest_priority_index= "
                    << new_installation_index;
    }
  }

  if (new_installation_index != -1) {
    installation_store_.mutable_installations(new_installation_index)
        ->set_is_successful(false);
    installation_store_.mutable_installations(new_installation_index)
        ->set_num_tries_left(IM_MAX_NUM_TRIES);

    if (!SaveInstallationStore()) {
      SB_LOG(ERROR) << "SelectNewInstallationIndex: failed to store";
      return IM_ERROR;
    }

    SB_DLOG(INFO) << "SelectNewInstallationIndex: " << DumpInstallationSlots();
    return new_installation_index;
  }
  return IM_ERROR;
}

int InstallationManager::ResetInstallation(int installation_index) {
  if (!initialized_) {
    SB_LOG(ERROR) << "ResetInstallation: not initialized";
    return IM_ERROR;
  }

  // invalid index or the system image.
  if (installation_index == -1 || installation_index == 0) {
    return IM_ERROR;
  }

  installation_store_.mutable_installations(installation_index)
      ->set_is_successful(false);
  installation_store_.mutable_installations(installation_index)
      ->set_num_tries_left(IM_MAX_NUM_TRIES);

  if (!SaveInstallationStore()) {
    SB_LOG(ERROR) << "ResetInstallation: failed to store";
    return IM_ERROR;
  }

  SB_DLOG(INFO) << "ResetInstallation: " << DumpInstallationSlots();
  return IM_SUCCESS;
}

int InstallationManager::RequestRollForwardToInstallation(
    int installation_index) {
  if (!initialized_) {
    SB_LOG(ERROR) << "RequestRollForwardToInstallation: not initialized";
    return IM_ERROR;
  }
  if (!IsValidIndex(installation_index)) {
    SB_LOG(ERROR) << "RequestRollForwardToInstallation: invalid index"
                  << installation_index;
    return IM_ERROR;
  }
  installation_store_.set_roll_forward_to_installation(installation_index);
  return SaveInstallationStore() ? IM_SUCCESS : IM_ERROR;
}

bool InstallationManager::SaveInstallationStore() {
  ValidatePriorities();

  if (IM_MAX_INSTALLATION_STORE_SIZE < installation_store_.ByteSize()) {
    SB_LOG(ERROR) << "SaveInstallationStore: Data too large"
                  << installation_store_.ByteSize();
    return false;
  }

  const size_t buf_size = installation_store_.ByteSize();
  std::vector<char> buf(buf_size, 0);

  int result = installation_store_.roll_forward_to_installation();
#if !SB_IS(EVERGREEN_COMPATIBLE_LITE)
  loader_app::SetPendingRestart(result != -1);
#endif

  installation_store_.SerializeToArray(buf.data(),
                                       installation_store_.ByteSize());

  if (!SbFileAtomicReplace(store_path_.c_str(), buf.data(),
                           installation_store_.ByteSize())) {
    SB_LOG(ERROR)
        << "SaveInstallationStore: Failed to store installation store: "
        << store_path_;
    return false;
  }
  SB_DLOG(INFO) << "SaveInstallationStore successful";
  return true;
}

bool InstallationManager::InitInstallationStorePath() {
  std::vector<char> storage_dir(kSbFileMaxPath);

  if (!SbSystemGetPath(kSbSystemPathStorageDirectory, storage_dir.data(),
                       kSbFileMaxPath)) {
    SB_LOG(ERROR) << "InitInstallationStorePath: Failed to get "
                     "kSbSystemPathStorageDirectory";
    return false;
  }
  storage_dir_ = storage_dir.data();
  store_path_ = storage_dir.data();
  store_path_ += kSbFileSepString;
  store_path_ += IM_STORE_FILE_NAME_PREFIX;
  store_path_ += app_key_;
  store_path_ += IM_STORE_FILE_NAME_SUFFIX;

  std::vector<char> content_dir(kSbFileMaxPath);
  if (!SbSystemGetPath(kSbSystemPathContentDirectory, content_dir.data(),
                       kSbFileMaxPath)) {
    return false;
  }
  content_dir_ = content_dir.data();
  return true;
}

bool InstallationManager::IsValidIndex(int index) {
  return index >= 0 && index < max_num_installations_;
}

void InstallationManager::ValidatePriorities() {
  std::set<int> priorities;
  for (int i = 0; i < max_num_installations_; i++) {
    priorities.insert(installation_store_.installations(i).priority());
  }
  for (int i = 0; i < max_num_installations_; i++) {
    SB_DCHECK(priorities.find(i) != priorities.end());
  }
  SB_DCHECK(priorities.size() == max_num_installations_);
}

bool InstallationManager::LoadInstallationStore() {
  SbFile file;

  SB_LOG(INFO) << "StorePath=" << store_path_;
  file = SbFileOpen(store_path_.c_str(), kSbFileOpenOnly | kSbFileRead, NULL,
                    NULL);
  if (!file) {
    SB_LOG(WARNING) << "Failed to open file: " << store_path_;
    return false;
  }

  char buf[IM_MAX_INSTALLATION_STORE_SIZE];
  int count = SbFileReadAll(file, buf, IM_MAX_INSTALLATION_STORE_SIZE);
  SB_DLOG(INFO) << "SbFileReadAll: count=" << count;
  if (count == -1) {
    LogLastSystemError("SbFileReadAll failed");
    return false;
  }
  if (!installation_store_.ParseFromArray(buf, count)) {
    SB_LOG(ERROR) << "LoadInstallationStore: Unable to parse storage";
    return false;
  }
  SbFileClose(file);
  return true;
}

bool InstallationManager::GetInstallationPathInternal(int installation_index,
                                                      char* path,
                                                      int path_length) {
  if (!IsValidIndex(installation_index)) {
    SB_LOG(ERROR) << "GetInstallationPath: invalid index" << installation_index;
    return false;
  }
  if (!path) {
    SB_LOG(ERROR) << "GetInstallationPath: path is null";
    return false;
  }
  // SLOT_0 is placed in |kSbSystemPathContentDirectory|, under the subdirectory
  // 'app/cobalt'.
  if (installation_index == 0) {
    snprintf(path, path_length, "%s%s%s%s%s", content_dir_.c_str(),
             kSbFileSepString, "app", kSbFileSepString, "cobalt");
  } else {
    snprintf(path, path_length, "%s%s%s%d", storage_dir_.c_str(),
             kSbFileSepString, "installation_", installation_index);
  }

  return true;
}

bool InstallationManager::CreateInstallationDirs() {
  std::vector<char> path(kSbFileMaxPath);
  for (int i = 0; i < max_num_installations_; i++) {
    // SLOT_0 is placed in |kSbSystemPathContentDirectory|, under the
    // subdirectory 'app/cobalt'.
    if (i == 0) {
      continue;
    }
    if (!GetInstallationPathInternal(i, path.data(), kSbFileMaxPath)) {
      return false;
    }

    if (mkdir(path.data(), 0700) != 0 && !SbDirectoryCanOpen(path.data())) {
      return false;
    }
  }
  return true;
}

bool InstallationManager::CleanInstallationDirs() {
  std::vector<char> path(kSbFileMaxPath);
  // The index 0 slot is under the content directory.
  for (int i = 1; i < max_num_installations_; i++) {
    if (!GetInstallationPathInternal(i, path.data(), kSbFileMaxPath)) {
      return false;
    }
    if (!SbFileDeleteRecursive(path.data(), true)) {
      return false;
    }
  }
  return true;
}

}  // namespace installation_manager
}  // namespace loader_app
}  // namespace starboard

#ifdef __cplusplus
extern "C" {
#endif

starboard::scoped_ptr<
    starboard::loader_app::installation_manager::InstallationManager>
    g_installation_manager_;

// Global Installation Manager Mutex.
SB_ONCE_INITIALIZE_FUNCTION(starboard::Mutex, GetImMutex);

int ImInitialize(int max_num_installations, const char* app_key) {
  starboard::ScopedLock lock(*GetImMutex());
  if (g_installation_manager_.get() == NULL) {
    g_installation_manager_.reset(
        new starboard::loader_app::installation_manager::InstallationManager(
            max_num_installations, app_key));
  }
  return g_installation_manager_->Initialize();
}

int ImGetAppKey(char* app_key, int app_key_length) {
  starboard::ScopedLock lock(*GetImMutex());
  return g_installation_manager_->GetAppKey(app_key, app_key_length);
}

int ImGetMaxNumberInstallations() {
  starboard::ScopedLock lock(*GetImMutex());
  return g_installation_manager_->GetMaxNumberInstallations();
}

void ImUninitialize() {
  starboard::ScopedLock lock(*GetImMutex());
  g_installation_manager_.reset(NULL);
}

int ImReset() {
  starboard::ScopedLock lock(*GetImMutex());
  return g_installation_manager_->Reset();
}

int ImGetInstallationStatus(int installation_index) {
  starboard::ScopedLock lock(*GetImMutex());
  return g_installation_manager_->GetInstallationStatus(installation_index);
}

int ImGetInstallationNumTriesLeft(int installation_index) {
  starboard::ScopedLock lock(*GetImMutex());
  return g_installation_manager_->GetInstallationNumTriesLeft(
      installation_index);
}

int ImDecrementInstallationNumTries(int installation_index) {
  starboard::ScopedLock lock(*GetImMutex());
  return g_installation_manager_->DecrementInstallationNumTries(
      installation_index);
}

int ImGetCurrentInstallationIndex() {
  starboard::ScopedLock lock(*GetImMutex());
  return g_installation_manager_->GetCurrentInstallationIndex();
}

int ImResetInstallation(int installation_index) {
  starboard::ScopedLock lock(*GetImMutex());
  return g_installation_manager_->ResetInstallation(installation_index);
}

int ImSelectNewInstallationIndex() {
  starboard::ScopedLock lock(*GetImMutex());
  return g_installation_manager_->SelectNewInstallationIndex();
}

int ImGetInstallationPath(int installation_index, char* path, int path_length) {
  starboard::ScopedLock lock(*GetImMutex());
  return g_installation_manager_->GetInstallationPath(installation_index, path,
                                                      path_length);
}

int ImMarkInstallationSuccessful(int installation_index) {
  starboard::ScopedLock lock(*GetImMutex());
  return g_installation_manager_->MarkInstallationSuccessful(
      installation_index);
}

int ImRollForwardIfNeeded() {
  starboard::ScopedLock lock(*GetImMutex());
  return g_installation_manager_->RollForwardIfNeeded();
}

int ImRollForward(int installation_index) {
  starboard::ScopedLock lock(*GetImMutex());
  return g_installation_manager_->RollForward(installation_index);
}

int ImRevertToSuccessfulInstallation() {
  starboard::ScopedLock lock(*GetImMutex());
  return g_installation_manager_->RevertToSuccessfulInstallation();
}

int ImRequestRollForwardToInstallation(int installation_index) {
  starboard::ScopedLock lock(*GetImMutex());
  return g_installation_manager_->RequestRollForwardToInstallation(
      installation_index);
}

#ifdef __cplusplus
}  // extern "C"
#endif
