// Copyright 2019 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 <lib/async-loop/cpp/loop.h>
#include <lib/async/dispatcher.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/sys/cpp/service_directory.h>
#include <lib/vfs/cpp/composed_service_dir.h>
#include <lib/vfs/cpp/service.h>
#include <lib/vfs/cpp/testing/dir_test_util.h>

#include <fidl/examples/echo/cpp/fidl.h>

#include "gtest/gtest.h"

namespace {

using vfs_tests::Dirent;

class EchoImpl : public fidl::examples::echo::Echo {
 public:
  EchoImpl(std::string ans) : ans_(ans) {}

  void EchoString(fidl::StringPtr value, EchoStringCallback callback) override { callback(ans_); }

 private:
  std::string ans_;
};

class ComposedServiceDirectorySimpleTest : public vfs_tests::DirConnection {
 public:
  vfs::internal::Directory* GetDirectoryNode() override { return &dir_; }

  ComposedServiceDirectorySimpleTest() : loop_(&kAsyncLoopConfigNoAttachToThread) {
    dir_.AddService("echo1", GetFakeService("echo1", loop_.dispatcher()));
    dir_.AddService("echo2", GetFakeService("echo2", loop_.dispatcher()));
    dir_.AddService("echo3", GetFakeService("echo3", loop_.dispatcher()));
    backing_dir_.AddEntry("echo1", GetFakeService("fallback_echo1", loop_.dispatcher()));
    backing_dir_.AddEntry("echo4", GetFakeService("fallback_echo4", loop_.dispatcher()));
    backing_dir_.AddEntry("echo5", GetFakeService("fallback_echo5", loop_.dispatcher()));

    dir_.set_fallback(GetConnection(&backing_dir_));
    loop_.StartThread("vfs test thread");
  }

  fuchsia::io::DirectoryPtr GetConnection(vfs::internal::Directory* dir) {
    fuchsia::io::DirectoryPtr ptr;
    dir->Serve(fuchsia::io::OPEN_RIGHT_READABLE | fuchsia::io::OPEN_RIGHT_WRITABLE,
               ptr.NewRequest().TakeChannel(), loop_.dispatcher());
    return ptr;
  }

  fuchsia::io::DirectorySyncPtr GetSyncConnection(vfs::internal::Directory* dir) {
    fuchsia::io::DirectorySyncPtr ptr;
    dir->Serve(fuchsia::io::OPEN_RIGHT_READABLE | fuchsia::io::OPEN_RIGHT_WRITABLE,
               ptr.NewRequest().TakeChannel(), loop_.dispatcher());
    return ptr;
  }

 protected:
  vfs::PseudoDir backing_dir_;
  vfs::ComposedServiceDir dir_;
  std::vector<std::unique_ptr<EchoImpl>> echo_impls_;
  fidl::BindingSet<fidl::examples::echo::Echo> bindings_;
  async::Loop loop_;

  std::unique_ptr<vfs::Service> GetFakeService(const std::string& ans,
                                               async_dispatcher_t* dispatcher) {
    auto echo = std::make_unique<EchoImpl>(ans);
    auto service = std::make_unique<vfs::Service>(bindings_.GetHandler(echo.get(), dispatcher));
    echo_impls_.push_back(std::move(echo));
    return service;
  }
};

TEST_F(ComposedServiceDirectorySimpleTest, ConnectToServices) {
  auto dir_connection = GetConnection(&dir_);
  sys::ServiceDirectory service_directory(std::move(dir_connection));
  std::string services[] = {"echo1", "echo2", "echo3"};

  // connect to services and test
  for (auto& s : services) {
    fidl::examples::echo::EchoSyncPtr ptr;
    service_directory.Connect(s, ptr.NewRequest().TakeChannel());
    fidl::StringPtr ans;
    ptr->EchoString("hello", &ans);
    EXPECT_EQ(s, ans);
  }

  std::string fallback_services[] = {"echo4", "echo5"};

  for (auto& s : fallback_services) {
    fidl::examples::echo::EchoSyncPtr ptr;
    service_directory.Connect(s, ptr.NewRequest().TakeChannel());
    fidl::StringPtr ans;
    ptr->EchoString("hello", &ans);
    EXPECT_EQ("fallback_" + s, ans);
  }
}

TEST_F(ComposedServiceDirectorySimpleTest, ReadDir) {
  auto ptr = GetSyncConnection(&dir_);

  std::vector<Dirent> expected_dirents = {
      Dirent::DirentForDot(),
      Dirent::DirentForService("echo1"),
      Dirent::DirentForService("echo2"),
      Dirent::DirentForService("echo3"),
  };
  AssertReadDirents(ptr, 1024, expected_dirents);
}

}  // namespace
