/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * 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 <app_info.h>

#include "base/logging.h"
#include "base/mutex.h"
#include "base/safe_map.h"
#include "thread-inl.h"

namespace art {

static constexpr const char* kUnknownValue = "unknown";

AppInfo::AppInfo()
    : update_mutex_("app_info_update_mutex", LockLevel::kGenericBottomLock) {}

// Converts VMRuntime.java constansts to a CodeType.
AppInfo::CodeType AppInfo::FromVMRuntimeConstants(uint32_t code_type) {
  switch (code_type) {
    case kVMRuntimePrimaryApk : return CodeType::kPrimaryApk;
    case kVMRuntimeSplitApk : return CodeType::kPrimaryApk;
    case kVMRuntimeSecondaryDex : return CodeType::kSecondaryDex;
    default:
      LOG(WARNING) << "Unknown code type: " << code_type;
      return CodeType::kUnknown;
  }
}

static const char* CodeTypeName(AppInfo::CodeType code_type) {
  switch (code_type) {
    case AppInfo::CodeType::kPrimaryApk : return "primary-apk";
    case AppInfo::CodeType::kSplitApk : return "split-apk";
    case AppInfo::CodeType::kSecondaryDex : return "secondary-dex";
    case AppInfo::CodeType::kUnknown : return "unknown";
  }
}

void AppInfo::RegisterAppInfo(const std::string& package_name,
                              const std::vector<std::string>& code_paths,
                              const std::string& cur_profile_path,
                              const std::string& ref_profile_path,
                              AppInfo::CodeType code_type) {
  MutexLock mu(Thread::Current(), update_mutex_);

  package_name_ = package_name;

  for (const std::string& code_path : code_paths) {
    CodeLocationInfo& cli = registered_code_locations_.GetOrCreate(
        code_path, []() { return CodeLocationInfo(); });
    cli.cur_profile_path = cur_profile_path;
    cli.ref_profile_path = ref_profile_path;
    cli.code_type = code_type;

    VLOG(startup) << "Registering code path. "
        << "\npackage_name=" << package_name
        << "\ncode_path=" << code_path
        << "\ncode_type=" << CodeTypeName(code_type)
        << "\ncur_profile=" << cur_profile_path
        << "\nref_profile=" << ref_profile_path;
  }
}

void AppInfo::RegisterOdexStatus(const std::string& code_path,
                                 const std::string& compiler_filter,
                                 const std::string& compilation_reason,
                                 const std::string& odex_status) {
  MutexLock mu(Thread::Current(), update_mutex_);

  CodeLocationInfo& cli = registered_code_locations_.GetOrCreate(
      code_path, []() { return CodeLocationInfo(); });
  cli.compiler_filter = compiler_filter;
  cli.compilation_reason = compilation_reason;
  cli.odex_status = odex_status;

  VLOG(startup) << "Registering odex status. "
        << "\ncode_path=" << code_path
        << "\ncompiler_filter=" << compiler_filter
        << "\ncompilation_reason=" << compilation_reason
        << "\nodex_status=" << odex_status;
}

bool AppInfo::HasRegisteredAppInfo() {
  MutexLock mu(Thread::Current(), update_mutex_);

  return package_name_.has_value();
}

void AppInfo::GetPrimaryApkOptimizationStatus(
    std::string* out_compiler_filter,
    std::string* out_compilation_reason) {
  MutexLock mu(Thread::Current(), update_mutex_);

  for (const auto& it : registered_code_locations_) {
    const CodeLocationInfo& cli = it.second;
    if (cli.code_type == CodeType::kPrimaryApk) {
      *out_compiler_filter = cli.compiler_filter.value_or(kUnknownValue);
      *out_compilation_reason = cli.compilation_reason.value_or(kUnknownValue);
      return;
    }
  }
  *out_compiler_filter = kUnknownValue;
  *out_compilation_reason = kUnknownValue;
}

AppInfo::CodeType AppInfo::GetRegisteredCodeType(const std::string& code_path) {
  MutexLock mu(Thread::Current(), update_mutex_);

  const auto it = registered_code_locations_.find(code_path);
  return it != registered_code_locations_.end() ? it->second.code_type : CodeType::kUnknown;
}

std::ostream& operator<<(std::ostream& os, AppInfo& rhs) {
  MutexLock mu(Thread::Current(), rhs.update_mutex_);

  os << "AppInfo for package_name=" << rhs.package_name_.value_or(kUnknownValue) << "\n";
  for (const auto& it : rhs.registered_code_locations_) {
    const std::string code_path = it.first;
    const AppInfo::CodeLocationInfo& cli = it.second;

    os << "\ncode_path=" << code_path
        << "\ncode_type=" << CodeTypeName(cli.code_type)
        << "\ncompiler_filter=" << cli.compiler_filter.value_or(kUnknownValue)
        << "\ncompilation_reason=" << cli.compilation_reason.value_or(kUnknownValue)
        << "\nodex_status=" << cli.odex_status.value_or(kUnknownValue)
        << "\ncur_profile=" << cli.cur_profile_path.value_or(kUnknownValue)
        << "\nref_profile=" << cli.ref_profile_path.value_or(kUnknownValue)
        << "\n";
  }
  return os;
}

std::string AppInfo::GetPrimaryApkReferenceProfile() {
  MutexLock mu(Thread::Current(), update_mutex_);

  for (const auto& it : registered_code_locations_) {
    const CodeLocationInfo& cli = it.second;
    if (cli.code_type == CodeType::kPrimaryApk) {
      return cli.ref_profile_path.value_or("");
    }
  }
  return "";
}


}  // namespace art
