// Copyright 2020 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 <sys/time.h>

#include <condition_variable>
#include <memory>
#include <mutex>
#include <thread>

#include <gtest/gtest.h>

#include "src/developer/shell/mirror/client.h"
#include "src/developer/shell/mirror/command_line_options.h"
#include "src/developer/shell/mirror/server.h"
#include "src/developer/shell/mirror/test_shared.h"

namespace shell::mirror {

class ClientServerTest : public ::testing::Test {
 public:
  ClientServerTest() {}
};

class MessageLoopHolder {
 public:
  explicit MessageLoopHolder(std::unique_ptr<debug_ipc::PlatformMessageLoop> ptr)
      : ptr_(std::move(ptr)) {}
  ~MessageLoopHolder() { ptr_->Cleanup(); }
  debug_ipc::PlatformMessageLoop* operator->() { return ptr_.get(); }
  debug_ipc::PlatformMessageLoop* get() { return ptr_.get(); }

 private:
  std::unique_ptr<debug_ipc::PlatformMessageLoop> ptr_;
};

TEST_F(ClientServerTest, RoundTrip) {
  const std::string kDataDir = "/client_server_test_tmp";
  FileRepo repo(&kAsyncLoopConfigNoAttachToCurrentThread);
  repo.InitMemRepo(kDataDir);

  // Generate some fake files.
  std::vector<std::pair<std::string, std::string>> golden = {
      {kDataDir + "/z.txt", ""},
      {kDataDir + "/a.txt", "Once upon a midnight dreary, while I pondered, weak and weary,"},
      {kDataDir + "/b.txt", "Over many a quaint and curious volume of forgotten lore"},
      {kDataDir + "/c.txt", "While I nodded, nearly napping, suddenly there came a tapping,"},
      {kDataDir + "/d.txt", "As of some one gently rapping, rapping at my chamber door."}};

  repo.WriteFiles(golden);

  CommandLineOptions options;
  options.port = 0;
  options.path = kDataDir;

  std::condition_variable cond_var;
  std::mutex mutex;
  uint16_t port;

  std::thread server_thread([&options, &cond_var, &port]() {
    SocketServer server;
    SocketServer::ConnectionConfig config;
    config.port = options.port;
    config.path = options.path;
    Err err = server.RunInLoop(config, FROM_HERE, [&cond_var, &server, &port]() {
      port = server.GetPort();
      cond_var.notify_all();
    });
    ASSERT_TRUE(err.ok()) << err.msg;
  });

  // Wait until the server has started.
  {
    std::unique_lock<std::mutex> l(mutex);
    cond_var.wait(l);
  }

  std::string host_and_port = "[::1]:" + std::to_string(port);

  // Initialize connection and load results.
  client::ClientConnection load_connection;
  Err err = load_connection.Init(host_and_port);
  ASSERT_TRUE(err.ok()) << err.msg;
  // Impossibly high timeout, because we're a test.
  struct timeval tv;
  tv.tv_sec = 10000;
  tv.tv_usec = 0;
  Files files;
  err = load_connection.Load(&files, &tv);
  ASSERT_TRUE(err.ok()) << err.msg;

  // Initialize connection and kill server.
  client::ClientConnection kill_connection;
  err = kill_connection.Init(host_and_port);
  ASSERT_TRUE(err.ok()) << err.msg;
  err = kill_connection.KillServer();
  ASSERT_TRUE(err.ok()) << err.msg;
  server_thread.join();

  // Make sure results are as expected.
  ASSERT_EQ(files.size(), golden.size());
  for (const auto& file : files) {
    const auto& data = file.View();
    const auto& name = file.Name();
    bool found = false;
    for (size_t i = 0; i < golden.size(); i++) {
      if ((golden[i].first.substr(kDataDir.length() + 1) == name) && (golden[i].second == data)) {
        found = true;
        break;
      }
    }
    ASSERT_TRUE(found) << "Not found in expected: " << name << " with data \"" << data << "\"";
  }
}

}  // namespace shell::mirror
