// 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 "third_party/crashpad/wrapper/wrapper.h"

#include <map>
#include <vector>

#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "client/crash_report_database.h"
#include "client/crashpad_client.h"
#include "client/settings.h"
#include "starboard/configuration_constants.h"
#include "starboard/directory.h"
#include "starboard/file.h"
#include "starboard/system.h"
#include "third_party/crashpad/snapshot/sanitized/sanitization_information.h"

namespace third_party {
namespace crashpad {
namespace wrapper {

namespace {

// TODO: Get evergreen information from installation.
const std::string kCrashpadVersion = "1.0.0.0";
#if defined(STARBOARD_BUILD_TYPE_GOLD)
const std::string kUploadUrl("https://clients2.google.com/cr/report");
#else
const std::string kUploadUrl("https://clients2.google.com/cr/staging_report");
#endif

::crashpad::CrashpadClient* GetCrashpadClient() {
  static auto* crashpad_client = new ::crashpad::CrashpadClient();
  return crashpad_client;
}

base::FilePath GetPathToCrashpadHandlerBinary() {
  std::vector<char> exe_path(kSbFileMaxPath);
  if (!SbSystemGetPath(
          kSbSystemPathExecutableFile, exe_path.data(), kSbFileMaxPath)) {
    LOG(ERROR) << "Couldn't retrieve path to crashpad_handler binary.";
    return base::FilePath("");
  }
  base::FilePath exe_dir_path = base::FilePath(exe_path.data()).DirName();
  std::string handler_path(exe_dir_path.value());
  handler_path.push_back(kSbFileSepChar);
  handler_path.append("crashpad_handler");
  return base::FilePath(handler_path.c_str());
}

base::FilePath GetDatabasePath() {
  std::vector<char> cache_directory_path(kSbFileMaxPath);
  if (!SbSystemGetPath(kSbSystemPathCacheDirectory,
                       cache_directory_path.data(),
                       kSbFileMaxPath)) {
    LOG(ERROR) << "Couldn't retrieve path to database directory";
    return base::FilePath("");
  }

  std::string crashpad_directory_path(cache_directory_path.data());
  crashpad_directory_path.push_back(kSbFileSepChar);
  crashpad_directory_path.append("crashpad_database");
  if (!SbDirectoryCreate(crashpad_directory_path.c_str())) {
    LOG(ERROR) << "Couldn't create directory for crashpad database";
    return base::FilePath("");
  }

  return base::FilePath(crashpad_directory_path.c_str());
}

void InitializeCrashpadDatabase(const base::FilePath database_directory_path) {
  std::unique_ptr<::crashpad::CrashReportDatabase> database =
      ::crashpad::CrashReportDatabase::Initialize(database_directory_path);
  ::crashpad::Settings* settings = database->GetSettings();
  settings->SetUploadsEnabled(true);
}

std::string GetProductName() {
#if SB_IS(EVERGREEN_COMPATIBLE)
  return "Cobalt_Evergreen";
#else
  return "Cobalt";
#endif
}

std::map<std::string, std::string> GetPlatformInfo() {
  std::map<std::string, std::string> platform_info;

  platform_info.insert({"starboard_version",
                        base::StringPrintf("Starboard/%d", SB_API_VERSION)});

  const size_t kSystemPropertyMaxLength = 1024;
  std::vector<char> value(kSystemPropertyMaxLength);
  bool result;

#if SB_API_VERSION >= 12
  result = SbSystemGetProperty(kSbSystemPropertySystemIntegratorName,
                               value.data(),
                               kSystemPropertyMaxLength);
#elif SB_API_VERSION == 11
  result = SbSystemGetProperty(kSbSystemPropertyOriginalDesignManufacturerName,
                               value.data(),
                               kSystemPropertyMaxLength);
#else
  result = SbSystemGetProperty(kSbSystemPropertyNetworkOperatorName,
                               value.data(),
                               kSystemPropertyMaxLength);
#endif
  if (result) {
    platform_info.insert({"system_integrator_name", value.data()});
  }

#if defined(STARBOARD_BUILD_TYPE_DEBUG)
  platform_info.insert({"build_configuration", "debug"});
#elif defined(STARBOARD_BUILD_TYPE_DEVEL)
  platform_info.insert({"build_configuration", "devel"});
#elif defined(STARBOARD_BUILD_TYPE_QA)
  platform_info.insert({"build_configuration", "qa"});
#elif defined(STARBOARD_BUILD_TYPE_GOLD)
  platform_info.insert({"build_configuration", "gold"});
#endif

  result = SbSystemGetProperty(kSbSystemPropertyUserAgentAuxField,
                               value.data(),
                               kSystemPropertyMaxLength);
  if (result) {
    platform_info.insert({"aux_field", value.data()});
  }

  result = SbSystemGetProperty(kSbSystemPropertyChipsetModelNumber,
                               value.data(),
                               kSystemPropertyMaxLength);
  if (result) {
    platform_info.insert({"chipset_model_number", value.data()});
  }

  result = SbSystemGetProperty(
      kSbSystemPropertyModelYear, value.data(), kSystemPropertyMaxLength);
  if (result) {
    platform_info.insert({"model_year", value.data()});
  }

  result = SbSystemGetProperty(
      kSbSystemPropertyFirmwareVersion, value.data(), kSystemPropertyMaxLength);
  if (result) {
    platform_info.insert({"firmware_version", value.data()});
  }

  result = SbSystemGetProperty(
      kSbSystemPropertyBrandName, value.data(), kSystemPropertyMaxLength);
  if (result) {
    platform_info.insert({"brand", value.data()});
  }

  result = SbSystemGetProperty(
      kSbSystemPropertyModelName, value.data(), kSystemPropertyMaxLength);
  if (result) {
    platform_info.insert({"model", value.data()});
  }

  return platform_info;
}

}  // namespace

void InstallCrashpadHandler() {
  ::crashpad::CrashpadClient* client = GetCrashpadClient();

  const base::FilePath handler_path = GetPathToCrashpadHandlerBinary();
  if (!SbFileExists(handler_path.value().c_str())) {
    LOG(WARNING) << "crashpad_handler not at expected location of "
                 << handler_path.value();
    return;
  }

  const base::FilePath database_directory_path = GetDatabasePath();
  const base::FilePath default_metrics_dir;
  const std::string product_name = GetProductName();
  std::map<std::string, std::string> default_annotations = {
      {"ver", kCrashpadVersion}, {"prod", product_name}};
  const std::vector<std::string> default_arguments = {};

  const std::map<std::string, std::string> platform_info = GetPlatformInfo();
  default_annotations.insert(platform_info.begin(), platform_info.end());

  InitializeCrashpadDatabase(database_directory_path);
  client->SetUnhandledSignals({});
  client->StartHandler(handler_path,
                       database_directory_path,
                       default_metrics_dir,
                       kUploadUrl,
                       default_annotations,
                       default_arguments,
                       false,
                       false);

  ::crashpad::SanitizationInformation sanitization_info = {0, 0, 0, 1};
  client->SendSanitizationInformationToHandler(sanitization_info);
}

bool AddEvergreenInfoToCrashpad(EvergreenInfo evergreen_info) {
  ::crashpad::CrashpadClient* client = GetCrashpadClient();
  return client->SendEvergreenInfoToHandler(evergreen_info);
}

bool AddAnnotationsToCrashpad(CrashpadAnnotations annotations) {
  ::crashpad::CrashpadClient* client = GetCrashpadClient();
  return client->SendAnnotationsToHandler(annotations);
}

}  // namespace wrapper
}  // namespace crashpad
}  // namespace third_party
