// 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/setup.h"

#include "base/command_line.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "tools/gn/filesystem_utils.h"
#include "tools/gn/input_file.h"
#include "tools/gn/parse_tree.h"
#include "tools/gn/parser.h"
#include "tools/gn/source_dir.h"
#include "tools/gn/source_file.h"
#include "tools/gn/tokenizer.h"
#include "tools/gn/value.h"

namespace {

// More logging.
const char kSwitchVerbose[] = "v";

const char kSwitchRoot[] = "root";
const char kSecondarySource[] = "secondary";

const base::FilePath::CharType kGnFile[] = FILE_PATH_LITERAL(".gn");

base::FilePath FindDotFile(const base::FilePath& current_dir) {
  base::FilePath try_this_file = current_dir.Append(kGnFile);
  if (base::PathExists(try_this_file))
    return try_this_file;

  base::FilePath with_no_slash = current_dir.StripTrailingSeparators();
  base::FilePath up_one_dir = with_no_slash.DirName();
  if (up_one_dir == current_dir)
    return base::FilePath();  // Got to the top.

  return FindDotFile(up_one_dir);
}

}  // namespace

Setup::Setup()
    : dotfile_toolchain_(Label()),
      dotfile_settings_(&dotfile_build_settings_, &dotfile_toolchain_,
                        std::string()),
      dotfile_scope_(&dotfile_settings_) {
}

Setup::~Setup() {
}

bool Setup::DoSetup() {
  CommandLine* cmdline = CommandLine::ForCurrentProcess();

  scheduler_.set_verbose_logging(cmdline->HasSwitch(kSwitchVerbose));

  if (!FillSourceDir(*cmdline))
    return false;
  if (!RunConfigFile())
    return false;
  if (!FillOtherConfig(*cmdline))
    return false;

  // FIXME(brettw) get python path!
/*#if defined(OS_WIN)
  build_settings_.set_python_path(base::FilePath(
      //L"P:\\depot_tools\\python_bin\\python.exe"));
      L"C:\\apps\\depot_tools\\python_bin\\python.exe"));
#else*/
  build_settings_.set_python_path(base::FilePath("python"));
//#endif

  build_settings_.SetBuildDir(SourceDir("//out/gn/"));

  return true;
}

bool Setup::Run() {
  // Load the root build file and start runnung.
  build_settings_.toolchain_manager().StartLoadingUnlocked(
      SourceFile("//BUILD.gn"));
  if (!scheduler_.Run())
    return false;

  Err err = build_settings_.item_tree().CheckForBadItems();
  if (err.has_error()) {
    err.PrintToStdout();
    return false;
  }
  return true;
}

bool Setup::FillSourceDir(const CommandLine& cmdline) {
  // Find the .gn file.
  base::FilePath root_path;

  // Prefer the command line args to the config file.
  base::FilePath relative_root_path = cmdline.GetSwitchValuePath(kSwitchRoot);
  if (!relative_root_path.empty()) {
    root_path = base::MakeAbsoluteFilePath(relative_root_path);
    dotfile_name_ = root_path.Append(kGnFile);
  } else {
    base::FilePath cur_dir;
    file_util::GetCurrentDirectory(&cur_dir);
    dotfile_name_ = FindDotFile(cur_dir);
    if (dotfile_name_.empty()) {
      Err(Location(), "Can't find source root.",
          "I could not find a \".gn\" file in the current directory or any "
          "parent,\nand the --root command-line argument was not specified.")
          .PrintToStdout();
      return false;
    }
    root_path = dotfile_name_.DirName();
  }

  if (scheduler_.verbose_logging())
    scheduler_.Log("Using source root", FilePathToUTF8(root_path));
  build_settings_.set_root_path(root_path);

  return true;
}

bool Setup::RunConfigFile() {
  if (scheduler_.verbose_logging())
    scheduler_.Log("Got dotfile", FilePathToUTF8(dotfile_name_));

  dotfile_input_file_.reset(new InputFile(SourceFile("//.gn")));
  if (!dotfile_input_file_->Load(dotfile_name_)) {
    Err(Location(), "Could not load dotfile.",
        "The file \"" + FilePathToUTF8(dotfile_name_) + "\" cound't be loaded")
        .PrintToStdout();
    return false;
  }

  Err err;
  dotfile_tokens_ = Tokenizer::Tokenize(dotfile_input_file_.get(), &err);
  if (err.has_error()) {
    err.PrintToStdout();
    return false;
  }

  dotfile_root_ = Parser::Parse(dotfile_tokens_, &err);
  if (err.has_error()) {
    err.PrintToStdout();
    return false;
  }

  dotfile_root_->AsBlock()->ExecuteBlockInScope(&dotfile_scope_, &err);
  if (err.has_error()) {
    err.PrintToStdout();
    return false;
  }

  return true;
}

bool Setup::FillOtherConfig(const CommandLine& cmdline) {
  Err err;

  // Secondary source path.
  SourceDir secondary_source;
  if (cmdline.HasSwitch(kSecondarySource)) {
    // Prefer the command line over the config file.
    secondary_source =
        SourceDir(cmdline.GetSwitchValueASCII(kSecondarySource));
  } else {
    // Read from the config file if present.
    const Value* secondary_value =
        dotfile_scope_.GetValue("secondary_source", true);
    if (secondary_value) {
      if (!secondary_value->VerifyTypeIs(Value::STRING, &err)) {
        err.PrintToStdout();
        return false;
      }
      build_settings_.SetSecondarySourcePath(
          SourceDir(secondary_value->string_value()));
    }
  }

  // Build config dir.
  const Value* build_config_value =
      dotfile_scope_.GetValue("buildconfig", true);
  if (!build_config_value) {
    Err(Location(), "No build config file.",
        "Your .gn file (\"" + FilePathToUTF8(dotfile_name_) + "\")\n"
        "didn't specify a \"buildconfig\" value.").PrintToStdout();
    return false;
  }
  build_settings_.set_build_config_file(
      SourceFile("//build/config/BUILDCONFIG.gn"));

  return true;
}
