// 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 "starboard/loader_app/drain_file.h"

#include <algorithm>
#include <cstring>
#include <string>
#include <vector>

#include "starboard/common/file.h"
#include "starboard/common/log.h"
#include "starboard/common/string.h"
#include "starboard/configuration_constants.h"
#include "starboard/directory.h"
#include "starboard/string.h"

#ifdef __cplusplus
extern "C" {
#endif

const SbTime kDrainFileAgeUnit = kSbTimeSecond;
const SbTime kDrainFileMaximumAge = kSbTimeHour;
const char kDrainFilePrefix[] = "d_";

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

namespace starboard {
namespace loader_app {
namespace {

std::string ExtractAppKey(const std::string& str) {
  const size_t begin = str.find_first_of('_') + 1;
  const size_t end = str.find_last_of('_');

  if ((begin == std::string::npos) || (end == std::string::npos) ||
      (end - begin < 1))
    return "";

  return str.substr(begin, end - begin);
}

SbTime ExtractTimestamp(const std::string& str) {
  const size_t index = str.find_last_of('_') + 1;

  if ((index == std::string::npos) || (index == str.size() - 1))
    return 0;

  const std::string timestamp = str.substr(index, str.size() - index);

  return SbTime(strtoull(timestamp.c_str(), NULL, 10)) * kDrainFileAgeUnit;
}

bool IsExpired(const std::string& filename) {
  const SbTime timestamp = ExtractTimestamp(filename);
  return timestamp + kDrainFileMaximumAge < SbTimeGetNow();
}

std::vector<std::string> FindAllWithPrefix(const std::string& dir,
                                           const std::string& prefix) {
  SbDirectory slot = SbDirectoryOpen(dir.c_str(), NULL);

  if (!SbDirectoryIsValid(slot)) {
    SB_LOG(ERROR) << "Failed to open provided directory '" << dir << "'";
    return std::vector<std::string>();
  }

  std::vector<std::string> filenames;

#if SB_API_VERSION >= 12
  std::vector<char> filename(kSbFileMaxName);

  while (SbDirectoryGetNext(slot, filename.data(), filename.size())) {
    if (!strcmp(filename.data(), ".") || !strcmp(filename.data(), ".."))
      continue;
    if (!strncmp(prefix.data(), filename.data(), prefix.size()))
      filenames.push_back(std::string(filename.data()));
  }
#else
  SbDirectoryEntry entry;

  while (SbDirectoryGetNext(slot, &entry)) {
    if (!strcmp(entry.name, ".") || !strcmp(entry.name, ".."))
      continue;
    if (!strncmp(prefix.data(), entry.name, prefix.size()))
      filenames.push_back(std::string(entry.name));
  }
#endif

  SbDirectoryClose(slot);
  return filenames;
}

void Rank(const char* dir, char* app_key, size_t len) {
  SB_DCHECK(dir);
  SB_DCHECK(app_key);

  std::vector<std::string> filenames = FindAllWithPrefix(dir, kDrainFilePrefix);

  std::remove_if(filenames.begin(), filenames.end(), IsExpired);

  if (filenames.empty())
    return;

  // This lambda compares two strings, each string being a drain file name. This
  // function returns |true| when |left| has an earlier timestamp than |right|,
  // or when |left| is ASCII-betically lower than |right| if their timestamps
  // are equal.
  auto compare_filenames = [](const std::string& left,
                              const std::string& right) -> bool {
    const SbTime left_timestamp = ExtractTimestamp(left);
    const SbTime right_timestamp = ExtractTimestamp(right);

    if (left_timestamp != right_timestamp)
      return left_timestamp < right_timestamp;

    const std::string left_app_key = ExtractAppKey(left);
    const std::string right_app_key = ExtractAppKey(right);

    return strncmp(left_app_key.c_str(), right_app_key.c_str(),
                   right_app_key.size()) < 0;
  };

  std::sort(filenames.begin(), filenames.end(), compare_filenames);

  const std::string& ranking_app_key = ExtractAppKey(filenames.front());

  if (starboard::strlcpy(app_key, ranking_app_key.c_str(), len) >= len)
    SB_LOG(ERROR) << "Returned value was truncated";
}

}  // namespace

namespace drain_file {

bool TryDrain(const char* dir, const char* app_key) {
  SB_DCHECK(dir);
  SB_DCHECK(app_key);

  std::vector<std::string> filenames = FindAllWithPrefix(dir, kDrainFilePrefix);

  for (const auto& filename : filenames) {
    if (IsExpired(filename))
      continue;
    if (filename.find(app_key) == std::string::npos)
      return false;
    SB_LOG(INFO) << "Found valid drain file '" << filename << "'";
    return true;
  }

  std::string filename(kDrainFilePrefix);
  filename.append(app_key);
  filename.append("_");
  filename.append(std::to_string(SbTimeGetNow() / kDrainFileAgeUnit));

  SB_DCHECK(filename.size() <= kSbFileMaxName);

  std::string path(dir);
  path.append(kSbFileSepString);
  path.append(filename);

  SbFileError error = kSbFileOk;
  SbFile file = SbFileOpen(path.c_str(), kSbFileCreateAlways | kSbFileWrite,
                           NULL, &error);

  SB_DCHECK(error == kSbFileOk);
  SB_DCHECK(SbFileClose(file));

  SB_LOG(INFO) << "Created drain file at '" << path << "'";

  return true;
}

bool RankAndCheck(const char* dir, const char* app_key) {
  SB_DCHECK(dir);
  SB_DCHECK(app_key);

  std::vector<char> ranking_app_key(kSbFileMaxName);

  Rank(dir, ranking_app_key.data(), ranking_app_key.size());

  return !strcmp(ranking_app_key.data(), app_key);
}

void ClearExpired(const char* dir) {
  SB_DCHECK(dir);
  std::vector<std::string> filenames = FindAllWithPrefix(dir, kDrainFilePrefix);

  for (const auto& filename : filenames) {
    if (!IsExpired(filename)) {
      continue;
    }
    const std::string path = dir + std::string(kSbFileSepString) + filename;
    if (!SbFileDelete(path.c_str())) {
      SB_LOG(ERROR) << "Failed to remove expired drain file at '" << path
                    << "'";
    }
  }
}

void ClearForApp(const char* dir, const char* app_key) {
  SB_DCHECK(dir);
  SB_DCHECK(app_key);

  const std::string prefix = std::string(kDrainFilePrefix) + app_key;
  const std::vector<std::string> filenames =
      FindAllWithPrefix(dir, prefix.c_str());

  for (const auto& filename : filenames) {
    const std::string path = dir + std::string(kSbFileSepString) + filename;
    if (!SbFileDelete(path.c_str())) {
      SB_LOG(ERROR) << "Failed to remove drain file at '" << path << "'";
    }
  }
}

void PrepareDirectory(const char* dir, const char* app_key) {
  SB_DCHECK(dir);
  SB_DCHECK(app_key);

  const std::string prefix = std::string(kDrainFilePrefix) + app_key;
  const std::vector<std::string> entries = FindAllWithPrefix(dir, "");

  for (const auto& entry : entries) {
    if (!strncmp(entry.c_str(), prefix.c_str(), prefix.size()))
      continue;

    std::string path(dir);
    path.append(kSbFileSepString);
    path.append(entry);

    SbFileDeleteRecursive(path.c_str(), false);
  }
}

bool IsAppDraining(const char* dir, const char* app_key) {
  SB_DCHECK(dir);
  SB_DCHECK(app_key);
  SB_DCHECK(strlen(app_key));

  std::string prefix(kDrainFilePrefix);
  prefix.append(app_key);

  const std::vector<std::string> filenames =
      FindAllWithPrefix(dir, prefix.c_str());

  for (const auto& filename : filenames) {
    if (!IsExpired(filename))
      return true;
  }
  return false;
}

bool IsAnotherAppDraining(const char* dir, const char* app_key) {
  SB_DCHECK(dir);
  SB_DCHECK(app_key);
  SB_DCHECK(strlen(app_key));
  std::vector<std::string> filenames = FindAllWithPrefix(dir, kDrainFilePrefix);

  for (const auto& filename : filenames) {
    if ((filename.find(app_key) != std::string::npos)) {
      continue;
    }
    if (!IsExpired(filename)) {
      return true;
    }
  }
  return false;
}

}  // namespace drain_file
}  // namespace loader_app
}  // namespace starboard

#ifdef __cplusplus
extern "C" {
#endif

bool DrainFileTryDrain(const char* dir, const char* app_key) {
  return starboard::loader_app::drain_file::TryDrain(dir, app_key);
}

bool DrainFileRankAndCheck(const char* dir, const char* app_key) {
  return starboard::loader_app::drain_file::RankAndCheck(dir, app_key);
}

void DrainFileClearExpired(const char* dir) {
  starboard::loader_app::drain_file::ClearExpired(dir);
}

void DrainFileClearForApp(const char* dir, const char* app_key) {
  starboard::loader_app::drain_file::ClearForApp(dir, app_key);
}

void DrainFilePrepareDirectory(const char* dir, const char* app_key) {
  starboard::loader_app::drain_file::PrepareDirectory(dir, app_key);
}

bool DrainFileIsAppDraining(const char* dir, const char* app_key) {
  return starboard::loader_app::drain_file::IsAppDraining(dir, app_key);
}

bool DrainFileIsAnotherAppDraining(const char* dir, const char* app_key) {
  return starboard::loader_app::drain_file::IsAnotherAppDraining(dir, app_key);
}

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