// Copyright 2018 The Chromium OS 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 <stdint.h>

#include <map>
#include <memory>
#include <string>
#include <utility>

#include <base/command_line.h>
#include <base/logging.h>
#include <base/macros.h>
#include <base/memory/ref_counted.h>
#include <brillo/daemons/dbus_daemon.h>
#include <brillo/syslog_logging.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/bus.h>

#include "appfuse/dbus_adaptors/org.chromium.ArcAppfuseProvider.h"
#include "arc/appfuse/appfuse_mount.h"

namespace {

constexpr char kMountRoot[] = "mount_root";

brillo::ErrorPtr CreateDBusError(const std::string& code,
                                 const std::string& message) {
  return brillo::Error::Create(FROM_HERE, brillo::errors::dbus::kDomain, code,
                               message);
}

class DBusAdaptor : public org::chromium::ArcAppfuseProviderAdaptor,
                    public org::chromium::ArcAppfuseProviderInterface,
                    public arc::appfuse::AppfuseMount::Delegate {
 public:
  explicit DBusAdaptor(scoped_refptr<dbus::Bus> bus)
      : org::chromium::ArcAppfuseProviderAdaptor(this),
        mount_root_(base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
            kMountRoot)),
        dbus_object_(
            nullptr,
            bus,
            dbus::ObjectPath(arc::appfuse::kArcAppfuseProviderServicePath)) {}

  ~DBusAdaptor() override = default;

  void RegisterAsync(
      const brillo::dbus_utils::AsyncEventSequencer::CompletionAction& cb) {
    RegisterWithDBusObject(&dbus_object_);
    dbus_object_.RegisterAsync(cb);
  }

  // org::chromium::ArcAppfuseProviderInterface overrides:
  bool Mount(brillo::ErrorPtr* error,
             uint32_t uid,
             int32_t mount_id,
             brillo::dbus_utils::FileDescriptor* out_fd) override {
    // Remove existing mount.
    auto it = mounts_.find(std::make_pair(uid, mount_id));
    if (it != mounts_.end()) {
      LOG(INFO) << "Unmounting an existing mount for a new mount: " << uid
                << " " << mount_id;
      if (!it->second->Unmount()) {
        LOG(ERROR) << "Failed to unmount an existing mount for a new mount: "
                   << uid << " " << mount_id;
        *error = CreateDBusError(DBUS_ERROR_FAILED, "Failed to unmount");
        return false;
      }
      mounts_.erase(it);
    }
    // Create a new mount.
    auto mount = std::make_unique<arc::appfuse::AppfuseMount>(mount_root_, uid,
                                                              mount_id, this);
    base::ScopedFD fd = mount->Mount();
    if (!fd.is_valid()) {
      LOG(ERROR) << "Failed to mount: " << uid << " " << mount_id;
      *error = CreateDBusError(DBUS_ERROR_FAILED, "Failed to mount");
      return false;
    }
    mounts_[std::make_pair(uid, mount_id)] = std::move(mount);
    *out_fd = std::move(fd);
    return true;
  }

  bool Unmount(brillo::ErrorPtr* error,
               uint32_t uid,
               int32_t mount_id) override {
    auto it = mounts_.find(std::make_pair(uid, mount_id));
    if (it == mounts_.end()) {
      LOG(ERROR) << "No mount found: " << uid << " " << mount_id;
      *error = CreateDBusError(DBUS_ERROR_FAILED, "No mount found");
      return false;
    }
    if (!it->second->Unmount()) {
      LOG(ERROR) << "Failed to unmount: " << uid << " " << mount_id;
      *error = CreateDBusError(DBUS_ERROR_FAILED, "Failed to unmount");
      return false;
    }
    mounts_.erase(it);
    return true;
  }

  bool OpenFile(brillo::ErrorPtr* error,
                uint32_t uid,
                int32_t mount_id,
                int32_t file_id,
                int32_t flags,
                brillo::dbus_utils::FileDescriptor* out_fd) override {
    auto it = mounts_.find(std::make_pair(uid, mount_id));
    if (it == mounts_.end()) {
      LOG(ERROR) << "No mount found: " << uid << " " << mount_id;
      *error = CreateDBusError(DBUS_ERROR_FAILED, "No mount found");
      return false;
    }
    base::ScopedFD fd = it->second->OpenFile(file_id, flags);
    if (!fd.is_valid()) {
      LOG(ERROR) << "Failed to open: " << uid << " " << mount_id;
      *error = CreateDBusError(DBUS_ERROR_FAILED, "Failed to open");
      return false;
    }
    *out_fd = std::move(fd);
    return true;
  }

  // AppfuseMount::Delegate override:
  void OnUnmounted(arc::appfuse::AppfuseMount* mount) override {
    mounts_.erase(std::make_pair(mount->uid(), mount->mount_id()));
  }

 private:
  const base::FilePath mount_root_;
  brillo::dbus_utils::DBusObject dbus_object_;

  // Maps (UID, mount ID) to AppfuseMount.
  using UIDMountIDPair = std::pair<uid_t, int>;
  using AppfuseMountMap =
      std::map<UIDMountIDPair, std::unique_ptr<arc::appfuse::AppfuseMount>>;
  AppfuseMountMap mounts_;

  DISALLOW_COPY_AND_ASSIGN(DBusAdaptor);
};

class Daemon : public brillo::DBusServiceDaemon {
 public:
  Daemon() : DBusServiceDaemon(arc::appfuse::kArcAppfuseProviderServiceName) {}
  ~Daemon() override = default;

 protected:
  void RegisterDBusObjectsAsync(
      brillo::dbus_utils::AsyncEventSequencer* sequencer) override {
    adaptor_ = std::make_unique<DBusAdaptor>(bus_);
    adaptor_->RegisterAsync(
        sequencer->GetHandler("RegisterAsync() failed.", true));
  }

 private:
  std::unique_ptr<DBusAdaptor> adaptor_;

  DISALLOW_COPY_AND_ASSIGN(Daemon);
};

}  // namespace

int main(int argc, char** argv) {
  base::CommandLine::Init(argc, argv);
  brillo::InitLog(brillo::kLogToSyslog | brillo::kLogToStderrIfTty);
  CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(kMountRoot))
      << "--" << kMountRoot << " must be specified.";
  return Daemon().Run();
}
