// Copyright 2013 The Flutter 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 "impeller/compiler/switches.h"

#include <filesystem>
#include <map>

#include "flutter/fml/file.h"

namespace impeller {
namespace compiler {

static const std::map<std::string, TargetPlatform> kKnownPlatforms = {
    {"metal-desktop", TargetPlatform::kMetalDesktop},
    {"metal-ios", TargetPlatform::kMetalIOS},
    {"opengl-es", TargetPlatform::kOpenGLES},
    {"opengl-desktop", TargetPlatform::kOpenGLDesktop},
    {"flutter-spirv", TargetPlatform::kFlutterSPIRV},
};

void Switches::PrintHelp(std::ostream& stream) {
  stream << std::endl << "Valid Argument are:" << std::endl;
  stream << "One of [";
  for (const auto& platform : kKnownPlatforms) {
    stream << " --" << platform.first;
  }
  stream << " ]" << std::endl;
  stream << "--input=<glsl_file>" << std::endl;
  stream << "--sl=<sl_output_file>" << std::endl;
  stream << "--spirv=<spirv_output_file>" << std::endl;
  stream << "[optional] --reflection-json=<reflection_json_file>" << std::endl;
  stream << "[optional] --reflection-header=<reflection_header_file>"
         << std::endl;
  stream << "[optional] --reflection-cc=<reflection_cc_file>" << std::endl;
  stream << "[optional,multiple] --include=<include_directory>" << std::endl;
  stream << "[optional,multiple] --define=<define>" << std::endl;
  stream << "[optional] --depfile=<depfile_path>" << std::endl;
}

Switches::Switches() = default;

Switches::~Switches() = default;

static TargetPlatform TargetPlatformFromCommandLine(
    const fml::CommandLine& command_line) {
  auto target = TargetPlatform::kUnknown;
  for (const auto& platform : kKnownPlatforms) {
    if (command_line.HasOption(platform.first)) {
      // If the platform has already been determined, the caller may have
      // specified multiple platforms. This is an error and only one must be
      // selected.
      if (target != TargetPlatform::kUnknown) {
        return TargetPlatform::kUnknown;
      }
      target = platform.second;
      // Keep going to detect duplicates.
    }
  }
  return target;
}

Switches::Switches(const fml::CommandLine& command_line)
    : target_platform(TargetPlatformFromCommandLine(command_line)),
      working_directory(std::make_shared<fml::UniqueFD>(fml::OpenDirectory(
          ToUtf8(std::filesystem::current_path().native()).c_str(),
          false,  // create if necessary,
          fml::FilePermission::kRead))),
      source_file_name(command_line.GetOptionValueWithDefault("input", "")),
      sl_file_name(command_line.GetOptionValueWithDefault("sl", "")),
      spirv_file_name(command_line.GetOptionValueWithDefault("spirv", "")),
      reflection_json_name(
          command_line.GetOptionValueWithDefault("reflection-json", "")),
      reflection_header_name(
          command_line.GetOptionValueWithDefault("reflection-header", "")),
      reflection_cc_name(
          command_line.GetOptionValueWithDefault("reflection-cc", "")),
      depfile_path(command_line.GetOptionValueWithDefault("depfile", "")) {
  if (!working_directory || !working_directory->is_valid()) {
    return;
  }

  for (const auto& include_dir_path : command_line.GetOptionValues("include")) {
    if (!include_dir_path.data()) {
      continue;
    }
    auto dir = std::make_shared<fml::UniqueFD>(fml::OpenDirectoryReadOnly(
        *working_directory, include_dir_path.data()));
    if (!dir || !dir->is_valid()) {
      continue;
    }

    IncludeDir dir_entry;
    dir_entry.name = include_dir_path;
    dir_entry.dir = std::move(dir);

    include_directories.emplace_back(std::move(dir_entry));
  }

  for (const auto& define : command_line.GetOptionValues("define")) {
    defines.emplace_back(define);
  }
}

bool Switches::AreValid(std::ostream& explain) const {
  bool valid = true;
  if (target_platform == TargetPlatform::kUnknown) {
    explain << "The target platform (only one) was not specified." << std::endl;
    valid = false;
  }

  if (!working_directory || !working_directory->is_valid()) {
    explain << "Could not figure out working directory." << std::endl;
    valid = false;
  }

  if (source_file_name.empty()) {
    explain << "Input file name was empty." << std::endl;
    valid = false;
  }

  if (sl_file_name.empty() && TargetPlatformNeedsSL(target_platform)) {
    explain << "Target shading language file name was empty." << std::endl;
    valid = false;
  }

  if (spirv_file_name.empty()) {
    explain << "Spirv file name was empty." << std::endl;
    valid = false;
  }
  return valid;
}

}  // namespace compiler
}  // namespace impeller
