// 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 "peridot/lib/fidl/json_xdr.h"
#include "peridot/lib/module_manifest/module_manifest_xdr.h"
#include "src/lib/pkg_url/fuchsia_pkg_url.h"
#include "src/lib/pkg_url/url_resolver.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 = std::move(callback)](
                         fuchsia::sys::PackagePtr package) {
        if (!package) {
          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 {
          callback({});
          return;
        }

        component::CmxFacetParser facet_parser;
        json::JSONParser json_parser;
        if (!facet_parser.ParseFromFileAt(fd.get(), cmx_path, &json_parser)) {
          FXL_LOG(WARNING) << "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()) {
          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
