// 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-loop/default.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_(&kAsyncLoopConfigNoAttachToCurrentThread) {
    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);
    ASSERT_TRUE(ans.has_value());
    EXPECT_EQ(s, ans.value());
  }

  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);
    ASSERT_TRUE(ans.has_value());
    EXPECT_EQ("fallback_" + s, ans.value());
  }
}

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
