// Copyright 2018 The Fuchsia 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 "peridot/lib/module_manifest/module_facet_reader_impl.h"

#include "lib/cmx_facet_parser/cmx_facet_parser.h"
#include "lib/component/cpp/startup_context.h"
#include "lib/fsl/io/fd.h"
#include "lib/json/json_parser.h"
#include "lib/pkg_url/fuchsia_pkg_url.h"
#include "lib/pkg_url/url_resolver.h"
#include "peridot/lib/fidl/json_xdr.h"
#include "peridot/lib/module_manifest/module_manifest_xdr.h"

namespace modular {
namespace {

constexpr char kModuleFacetName[] = "fuchsia.module";

}  // namespace

ModuleFacetReaderImpl::ModuleFacetReaderImpl(fuchsia::sys::LoaderPtr loader)
    : loader_(std::move(loader)) {}

ModuleFacetReaderImpl::~ModuleFacetReaderImpl() {}

void ModuleFacetReaderImpl::GetModuleManifest(
    const std::string& module_url, GetModuleManifestCallback callback) {
  auto canonical_url = component::CanonicalizeURL(module_url);
  loader_->LoadUrl(canonical_url, [canonical_url,
                                   callback](fuchsia::sys::PackagePtr package) {
    if (!package) {
      FXL_LOG(ERROR) << "Could not resolve URL: " << canonical_url;
      callback({});
      return;
    }
    fxl::UniqueFD fd =
        fsl::OpenChannelAsFileDescriptor(std::move(package->directory));

    component::FuchsiaPkgUrl pkg_url;
    std::string cmx_path;
    if (pkg_url.Parse(package->resolved_url)) {
      if (!pkg_url.resource_path().empty()) {
        // If the url has a resource, assume that's the cmx.
        cmx_path = pkg_url.resource_path();
      } else {
        // It's possible the url does not have a resource, in which case either
        // the cmx exists at meta/<package_name.cmx> or it does not exist.
        cmx_path = pkg_url.GetDefaultComponentCmxPath();
      }
    } else {
      FXL_LOG(ERROR) << "Could not parse package URL: "
                     << package->resolved_url;
      callback({});
    }

    component::CmxFacetParser facet_parser;
    json::JSONParser json_parser;
    if (!facet_parser.ParseFromFileAt(fd.get(), cmx_path, &json_parser)) {
      FXL_LOG(ERROR) << "Could not parse CMX manifest " << cmx_path << ": "
                     << json_parser.error_str();
      callback({});
      return;
    }

    const auto& mod_facet = facet_parser.GetSection(kModuleFacetName);
    if (mod_facet.IsNull()) {
      FXL_LOG(INFO) << "No module facet declared for module="
                    << package->resolved_url;
      callback({});
      return;
    }

    fuchsia::modular::ModuleManifestPtr module_manifest;
    auto mod_facet_str = JsonValueToString(mod_facet);
    if (!XdrRead(mod_facet_str, &module_manifest, XdrModuleManifest)) {
      FXL_LOG(WARNING) << "Unable to parse manifest module facet for "
                       << package->resolved_url << ": " << mod_facet_str;
      callback({});
      return;
    }
    // TODO(MF-94): Deprecate ModuleManfiest.binary in favour of getting it from
    // the cmx manifest.
    module_manifest->binary = canonical_url;
    callback(std::move(module_manifest));
  });
}

}  // namespace modular
