// Copyright 2020 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 "components/update_client/cobalt_slot_management.h"

#include <algorithm>
#include <vector>

#include "base/files/file_util.h"
#include "base/values.h"
#include "cobalt/updater/utils.h"
#include "components/update_client/utils.h"
#include "starboard/configuration_constants.h"
#include "starboard/file.h"
#include "starboard/loader_app/app_key_files.h"
#include "starboard/loader_app/drain_file.h"

namespace update_client {

namespace {
bool CheckBadFileExists(const char* installation_path, const char* app_key) {
  std::string bad_app_key_file_path =
      starboard::loader_app::GetBadAppKeyFilePath(installation_path, app_key);
  SB_DCHECK(!bad_app_key_file_path.empty());
  LOG(INFO) << "bad_app_key_file_path: " << bad_app_key_file_path;
  LOG(INFO) << "bad_app_key_file_path SbFileExists: "
            << SbFileExists(bad_app_key_file_path.c_str());
  return !bad_app_key_file_path.empty() &&
         SbFileExists(bad_app_key_file_path.c_str());
}

uint64_t ComputeSlotSize(
    const CobaltExtensionInstallationManagerApi* installation_api,
    int index) {
  if (!installation_api) {
    LOG(WARNING) << "ComputeSlotSize: "
                 << "Missing installation manager extension.";
    return 0;
  }
  std::vector<char> installation_path(kSbFileMaxPath);
  if (installation_api->GetInstallationPath(index, installation_path.data(),
                                            kSbFileMaxPath) == IM_EXT_ERROR) {
    LOG(WARNING) << "ComputeSlotSize: "
                 << "Failed to get installation path for slot " << index;
    return 0;
  }
  int64_t slot_size =
      base::ComputeDirectorySize(base::FilePath(installation_path.data()));
  LOG(INFO) << "ComputeSlotSize: slot_size=" << slot_size;
  if (slot_size <= 0) {
    LOG(WARNING) << "ComputeSlotSize: "
                 << "Failed to compute slot " << index << " size";
    return 0;
  }
  return slot_size;
}
}  // namespace

CobaltSlotManagement::CobaltSlotManagement() : installation_api_(nullptr) {}

bool CobaltSlotManagement::Init(
    const CobaltExtensionInstallationManagerApi* installation_api) {
  LOG(INFO) << "CobaltSlotManagement::Init";

  installation_api_ = installation_api;

  // Make sure the index is reset
  installation_index_ = IM_EXT_INVALID_INDEX;
  if (!installation_api_) {
    LOG(ERROR) << "Failed to get installation manager";
    return false;
  }

  char app_key[IM_EXT_MAX_APP_KEY_LENGTH];
  if (installation_api_->GetAppKey(app_key, IM_EXT_MAX_APP_KEY_LENGTH) ==
      IM_EXT_ERROR) {
    LOG(ERROR) << "Failed to get app key.";
    return false;
  }
  app_key_ = app_key;
  initialized_ = true;
  return true;
}

bool CobaltSlotManagement::SelectSlot(base::FilePath* dir) {
  SB_DCHECK(initialized_);
  if (!initialized_) {
    return false;
  }
  LOG(INFO) << "CobaltSlotManagement::SelectSlot";
  int max_slots = installation_api_->GetMaxNumberInstallations();
  if (max_slots == IM_EXT_ERROR) {
    LOG(ERROR) << "Failed to get max number of slots";
    return false;
  }

  // Default invalid version.
  base::Version slot_candidate_version;
  int slot_candidate = -1;
  base::FilePath slot_candidate_path;

  // Iterate over all writeable slots - index >= 1.
  for (int i = 1; i < max_slots; i++) {
    LOG(INFO) << "CobaltSlotManagement::SelectSlot iterating slot=" << i;
    std::vector<char> installation_path(kSbFileMaxPath);
    if (installation_api_->GetInstallationPath(i, installation_path.data(),
                                               installation_path.size()) ==
        IM_EXT_ERROR) {
      LOG(ERROR) << "CobaltSlotManagement::SelectSlot: Failed to get "
                    "installation path for slot="
                 << i;
      continue;
    }

    SB_DLOG(INFO) << "CobaltSlotManagement::SelectSlot: installation_path = "
                  << installation_path.data();

    base::FilePath installation_dir(
        std::string(installation_path.begin(), installation_path.end()));

    // Cleanup all expired files from all apps.
    DrainFileClearExpired(installation_dir.value().c_str());

    // Cleanup all drain files from the current app.
    DrainFileClearForApp(installation_dir.value().c_str(), app_key_.c_str());

    base::Version version =
        cobalt::updater::ReadEvergreenVersion(installation_dir);
    if (!version.IsValid()) {
      LOG(INFO) << "CobaltSlotManagement::SelectSlot installed version invalid";
      if (!DrainFileIsAnotherAppDraining(installation_dir.value().c_str(),
                                         app_key_.c_str())) {
        LOG(INFO) << "CobaltSlotManagement::SelectSlot not draining";
        // Found empty slot.
        slot_candidate = i;
        slot_candidate_path = installation_dir;
        break;
      } else {
        // There is active draining from another updater so bail out.
        LOG(ERROR) << "CobaltSlotManagement::SelectSlot bailing out";
        return false;
      }
    } else if ((!slot_candidate_version.IsValid() ||
                slot_candidate_version > version)) {
      if (!DrainFileIsAnotherAppDraining(installation_dir.value().c_str(),
                                         app_key_.c_str())) {
        // Found a slot with older version that's not draining.
        LOG(INFO) << "CobaltSlotManagement::SelectSlot slot candidate: " << i;
        slot_candidate_version = version;
        slot_candidate = i;
        slot_candidate_path = installation_dir;
      } else {
        // There is active draining from another updater so bail out.
        LOG(ERROR) << "CobaltSlotManagement::SelectSlot bailing out";
        return false;
      }
    }
  }

  installation_index_ = slot_candidate;
  *dir = slot_candidate_path;

  if (installation_index_ == -1 ||
      !DrainFileTryDrain(dir->value().c_str(), app_key_.c_str())) {
    LOG(ERROR)
        << "CobaltSlotManagement::SelectSlot unable to find a slot, candidate="
        << installation_index_;
    return false;
  }
  return true;
}

bool CobaltSlotManagement::ConfirmSlot(const base::FilePath& dir) {
  SB_DCHECK(initialized_);
  if (!initialized_) {
    return false;
  }
  LOG(INFO) << "CobaltSlotManagement::ConfirmSlot ";
  if (!DrainFileRankAndCheck(dir.value().c_str(), app_key_.c_str())) {
    LOG(INFO) << "CobaltSlotManagement::ConfirmSlot: failed to lock slot ";
    return false;
  }

  // TODO: Double check the installed_version.

  // Use the installation slot
  LOG(INFO) << "Resetting the slot: " << installation_index_;
  if (installation_api_->ResetInstallation(installation_index_) ==
      IM_EXT_ERROR) {
    LOG(INFO) << "CobaltSlotManagement::ConfirmSlot: failed to reset slot ";
    return false;
  }

  // Remove all files and directories except for our ranking drain file.
  DrainFilePrepareDirectory(dir.value().c_str(), app_key_.c_str());

  return true;
}

void CobaltSlotManagement::CleanupAllDrainFiles() {
  SB_DCHECK(initialized_);
  if (!initialized_) {
    return;
  }

  int max_slots = installation_api_->GetMaxNumberInstallations();
  if (max_slots == IM_EXT_ERROR) {
    LOG(ERROR) << "CobaltSlotManagement::CleanupAllDrainFile: Failed to get "
                  "max number of slots";
    return;
  }

  // Iterate over all writeable installation slots.
  for (int i = 1; i < max_slots; i++) {
    LOG(INFO) << "CobaltSlotManagement::CleanupAllDrainFile iterating slot="
              << i;
    std::vector<char> installation_path(kSbFileMaxPath);
    if (installation_api_->GetInstallationPath(i, installation_path.data(),
                                               installation_path.size()) ==
        IM_EXT_ERROR) {
      LOG(ERROR) << "CobaltSlotManagement::CleanupAllDrainFile: Failed to get "
                    "installation path for slot="
                 << i;
      continue;
    }

    LOG(INFO)
        << "CobaltSlotManagement::CleanupAllDrainFile: installation_path = "
        << installation_path.data();

    base::FilePath installation_dir(
        std::string(installation_path.begin(), installation_path.end()));

    DrainFileClearForApp(installation_dir.value().c_str(), app_key_.c_str());
  }
}

int CobaltSlotManagement::GetInstallationIndex() {
  SB_DCHECK(initialized_);
  if (!initialized_) {
    return false;
  }
  return installation_index_;
}

bool CobaltFinishInstallation(
    const CobaltExtensionInstallationManagerApi* installation_api,
    int installation_index,
    const std::string& dir,
    const std::string& app_key) {
  std::string good_app_key_file_path =
      starboard::loader_app::GetGoodAppKeyFilePath(dir, app_key);
  SB_CHECK(!good_app_key_file_path.empty());
  if (!starboard::loader_app::CreateAppKeyFile(good_app_key_file_path)) {
    LOG(WARNING) << "Failed to create good app key file";
  }
  DrainFileClearForApp(dir.c_str(), app_key.c_str());
  int ret =
      installation_api->RequestRollForwardToInstallation(installation_index);
  if (ret == IM_EXT_ERROR) {
    LOG(ERROR) << "Failed to request roll forward.";
    return false;
  }
  return true;
}

bool CobaltQuickUpdate(
    const CobaltExtensionInstallationManagerApi* installation_api,
    const base::Version& current_version) {
  if (!current_version.IsValid()) {
    return false;
  }
  char app_key[IM_EXT_MAX_APP_KEY_LENGTH];
  if (installation_api->GetAppKey(app_key, IM_EXT_MAX_APP_KEY_LENGTH) ==
      IM_EXT_ERROR) {
    LOG(ERROR) << "CobaltQuickUpdate: Failed to get app key.";
    return true;
  }

  int max_slots = installation_api->GetMaxNumberInstallations();
  if (max_slots == IM_EXT_ERROR) {
    LOG(ERROR) << "CobaltQuickUpdate: Failed to get max number of slots.";
    return true;
  }

  // We'll find the newest version of the installation that satisfies the
  // requirements as the final candidate slot.
  base::Version slot_candidate_version("1.0.1");
  int slot_candidate = -1;

  // Iterate over all slots - index >= 0.
  for (int i = 0; i < max_slots; i++) {
    LOG(INFO) << "CobaltQuickInstallation: iterating slot=" << i;
    // Get the path to new installation.
    std::vector<char> installation_path(kSbFileMaxPath);
    if (installation_api->GetInstallationPath(i, installation_path.data(),
                                              installation_path.size()) ==
        IM_EXT_ERROR) {
      LOG(ERROR) << "CobaltQuickInstallation: Failed to get "
                 << "installation path for slot=" << i;
      continue;
    }

    SB_DLOG(INFO) << "CobaltQuickInstallation: installation_path = "
                  << installation_path.data();

    base::FilePath installation_dir = base::FilePath(
        std::string(installation_path.begin(), installation_path.end()));

    base::Version installed_version =
        cobalt::updater::ReadEvergreenVersion(installation_dir);

    std::string good_app_key_file_path =
        starboard::loader_app::GetGoodAppKeyFilePath(
            installation_dir.value().c_str(), app_key);
    if (!installed_version.IsValid()) {
      LOG(WARNING) << "CobaltQuickInstallation: invalid version ";
      continue;
    } else if (slot_candidate_version < installed_version &&
               current_version < installed_version &&
               (i == 0 || !DrainFileIsAnotherAppDraining(
                              installation_dir.value().c_str(), app_key) &&
                              !CheckBadFileExists(
                                  installation_dir.value().c_str(), app_key) &&
                              !SbFileExists(good_app_key_file_path.c_str()) &&
                              starboard::loader_app::AnyGoodAppKeyFile(
                                  installation_dir.value().c_str()))) {
      // Found a slot with newer version than the current version. It's either
      // the system image slot, or a writeable installation slot that's not
      // draining, and no bad file of current app exists, and a good file
      // exists from a another app, but not from the current app.
      // The final candidate is the newest version of the valid
      // candidates.
      LOG(INFO) << "CobaltQuickInstallation: slot candidate: " << i;
      slot_candidate_version = installed_version;
      slot_candidate = i;
    }
  }

  if (slot_candidate != -1) {
    if (installation_api->RequestRollForwardToInstallation(slot_candidate) !=
        IM_EXT_ERROR) {
      LOG(INFO) << "CobaltQuickInstallation: quick update succeeded.";
      return true;
    }
  }
  LOG(WARNING) << "CobaltQuickInstallation: quick update failed.";
  return false;
}

bool CobaltSkipUpdate(
    const CobaltExtensionInstallationManagerApi* installation_api,
    uint64_t min_free_space_bytes,
    int64_t free_space_bytes,
    uint64_t installation_cleanup_size) {
  LOG(INFO) << "CobaltSkipUpdate: "
            << " min_free_space_bytes=" << min_free_space_bytes
            << " free_space_bytes=" << free_space_bytes
            << " installation_cleanup_size=" << installation_cleanup_size;

  if (free_space_bytes < 0) {
    LOG(WARNING) << "CobaltSkipUpdate: "
                 << "Unable to determine free space";
    return false;
  }

  if (free_space_bytes + installation_cleanup_size < min_free_space_bytes) {
    LOG(WARNING) << "CobaltSkipUpdate: Not enough free space";
    return true;
  }

  return false;
}

uint64_t CobaltInstallationCleanupSize(
    const CobaltExtensionInstallationManagerApi* installation_api) {
  if (!installation_api) {
    LOG(WARNING) << "CobaltInstallationCleanupSize: "
                 << "Missing installation manager extension.";
    return 0;
  }
  int max_slots = installation_api->GetMaxNumberInstallations();
  if (max_slots == IM_EXT_ERROR) {
    LOG(ERROR)
        << "CobaltInstallationCleanupSize: Failed to get max number of slots.";
    return 0;
  }
  // Ignore the system slot 0 and start with slot 1.
  uint64_t min_slot_size = ComputeSlotSize(installation_api, 1);
  for (int i = 2; i < max_slots; i++) {
    uint64_t slot_size = ComputeSlotSize(installation_api, i);
    if (slot_size < min_slot_size) {
      min_slot_size = slot_size;
    }
  }

  return min_slot_size;
}
}  // namespace update_client
