// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "tools/gn/scope_per_file_provider.h"

#include <memory>

#include "tools/gn/filesystem_utils.h"
#include "tools/gn/settings.h"
#include "tools/gn/source_file.h"
#include "tools/gn/value.h"
#include "tools/gn/variables.h"

ScopePerFileProvider::ScopePerFileProvider(Scope* scope, bool allow_target_vars)
    : ProgrammaticProvider(scope), allow_target_vars_(allow_target_vars) {}

ScopePerFileProvider::~ScopePerFileProvider() = default;

const Value* ScopePerFileProvider::GetProgrammaticValue(
    const std::string_view& ident) {
  if (ident == variables::kCurrentToolchain)
    return GetCurrentToolchain();
  if (ident == variables::kDefaultToolchain)
    return GetDefaultToolchain();
  if (ident == variables::kPythonPath)
    return GetPythonPath();

  if (ident == variables::kRootBuildDir)
    return GetRootBuildDir();
  if (ident == variables::kRootGenDir)
    return GetRootGenDir();
  if (ident == variables::kRootOutDir)
    return GetRootOutDir();

  if (allow_target_vars_) {
    if (ident == variables::kTargetGenDir)
      return GetTargetGenDir();
    if (ident == variables::kTargetOutDir)
      return GetTargetOutDir();
  }
  return nullptr;
}

const Value* ScopePerFileProvider::GetCurrentToolchain() {
  if (!current_toolchain_) {
    current_toolchain_ = std::make_unique<Value>(
        nullptr,
        scope_->settings()->toolchain_label().GetUserVisibleName(false));
  }
  return current_toolchain_.get();
}

const Value* ScopePerFileProvider::GetDefaultToolchain() {
  if (!default_toolchain_) {
    default_toolchain_ = std::make_unique<Value>(
        nullptr,
        scope_->settings()->default_toolchain_label().GetUserVisibleName(
            false));
  }
  return default_toolchain_.get();
}

const Value* ScopePerFileProvider::GetPythonPath() {
  if (!python_path_) {
    python_path_ = std::make_unique<Value>(
        nullptr,
        FilePathToUTF8(scope_->settings()->build_settings()->python_path()));
  }
  return python_path_.get();
}

const Value* ScopePerFileProvider::GetRootBuildDir() {
  if (!root_build_dir_) {
    root_build_dir_ = std::make_unique<Value>(
        nullptr, DirectoryWithNoLastSlash(
                     scope_->settings()->build_settings()->build_dir()));
  }
  return root_build_dir_.get();
}

const Value* ScopePerFileProvider::GetRootGenDir() {
  if (!root_gen_dir_) {
    root_gen_dir_ = std::make_unique<Value>(
        nullptr, DirectoryWithNoLastSlash(GetBuildDirAsSourceDir(
                     BuildDirContext(scope_), BuildDirType::GEN)));
  }
  return root_gen_dir_.get();
}

const Value* ScopePerFileProvider::GetRootOutDir() {
  if (!root_out_dir_) {
    root_out_dir_ = std::make_unique<Value>(
        nullptr, DirectoryWithNoLastSlash(GetScopeCurrentBuildDirAsSourceDir(
                     scope_, BuildDirType::TOOLCHAIN_ROOT)));
  }
  return root_out_dir_.get();
}

const Value* ScopePerFileProvider::GetTargetGenDir() {
  if (!target_gen_dir_) {
    target_gen_dir_ = std::make_unique<Value>(
        nullptr, DirectoryWithNoLastSlash(GetScopeCurrentBuildDirAsSourceDir(
                     scope_, BuildDirType::GEN)));
  }
  return target_gen_dir_.get();
}

const Value* ScopePerFileProvider::GetTargetOutDir() {
  if (!target_out_dir_) {
    target_out_dir_ = std::make_unique<Value>(
        nullptr, DirectoryWithNoLastSlash(GetScopeCurrentBuildDirAsSourceDir(
                     scope_, BuildDirType::OBJ)));
  }
  return target_out_dir_.get();
}
