// Copyright 2016 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 <memory>
#include <utility>

#include <fuchsia/auth/cpp/fidl.h>
#include <fuchsia/modular/cpp/fidl.h>
#include <lib/app_driver/cpp/app_driver.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/callback/scoped_callback.h>
#include <lib/component/cpp/startup_context.h>
#include <lib/fxl/command_line.h>
#include <lib/fxl/logging.h>
#include <lib/fxl/macros.h>
#include <lib/fxl/memory/weak_ptr.h>
#include <lib/fxl/strings/string_number_conversions.h>
#include <lib/zx/eventpair.h>

#include "peridot/lib/fidl/single_service_app.h"
#include "peridot/public/lib/integration_testing/cpp/reporting.h"
#include "peridot/public/lib/integration_testing/cpp/testing.h"

namespace modular {

class Settings {
 public:
  explicit Settings(const fxl::CommandLine& command_line) {
    // device_name will be set to the device's hostname if it is empty or null
    device_name = command_line.GetOptionValueWithDefault("device_name", "");

    // default user is incognito
    user = command_line.GetOptionValueWithDefault("user", "");

    // If passed, runs as a test harness.
    test = command_line.HasOption("test");

    test_timeout_ms = testing::kTestTimeoutMilliseconds;

    if (command_line.HasOption("test_timeout_ms")) {
      std::string test_timeout_ms_string;
      command_line.GetOptionValue("test_timeout_ms", &test_timeout_ms_string);
      if (!fxl::StringToNumberWithError<uint64_t>(test_timeout_ms_string,
                                                  &test_timeout_ms)) {
        FXL_LOG(WARNING) << "Unable to parse timeout from '"
                         << test_timeout_ms_string << "'. Setting to default.";
      }
    }
  }

  std::string device_name;
  std::string user;
  uint64_t test_timeout_ms;
  bool test{};
};

// Implementation of the fuchsia::modular::BaseShell service that passes a
// command line configurable user name to its fuchsia::modular::UserProvider,
// and is able to run a story with a single module through its life cycle.
class DevBaseShellApp : modular::SingleServiceApp<fuchsia::modular::BaseShell>,
                        fuchsia::modular::UserWatcher {
 public:
  explicit DevBaseShellApp(component::StartupContext* const startup_context,
                           Settings settings)
      : SingleServiceApp(startup_context),
        settings_(std::move(settings)),
        user_watcher_binding_(this),
        weak_ptr_factory_(this) {
    if (settings_.test) {
      testing::Init(this->startup_context(), __FILE__);
      testing::Await(testing::kTestShutdown,
                     [this] { base_shell_context_->Shutdown(); });

      // Start a timer to quit in case a test component misbehaves and hangs. If
      // we hit the timeout, this is a test failure.
      async::PostDelayedTask(
          async_get_default_dispatcher(),
          callback::MakeScoped(weak_ptr_factory_.GetWeakPtr(),
                               [this] {
                                 FXL_LOG(WARNING) << "DevBaseShell timed out";
                                 testing::Fail("DevBaseShell timed out");
                                 base_shell_context_->Shutdown();
                               }),
          zx::msec(settings_.test_timeout_ms));
    }
  }

  ~DevBaseShellApp() override = default;

  // |SingleServiceApp|
  void Terminate(std::function<void()> done) override {
    if (settings_.test) {
      testing::Teardown(done);
    } else {
      done();
    }
  }

 private:
  // |SingleServiceApp|
  void CreateView(
      zx::eventpair view_token,
      fidl::InterfaceRequest<
          fuchsia::sys::ServiceProvider> /*incoming_services*/,
      fidl::InterfaceHandle<
          fuchsia::sys::ServiceProvider> /*outgoing_services*/) override {
    view_token_ = std::move(view_token);
    Connect();
  }

  // |fuchsia::modular::BaseShell|
  void Initialize(
      fidl::InterfaceHandle<fuchsia::modular::BaseShellContext>
          base_shell_context,
      fuchsia::modular::BaseShellParams base_shell_params) override {
    base_shell_context_.Bind(std::move(base_shell_context));
    base_shell_context_->GetUserProvider(user_provider_.NewRequest());

    Connect();
  }

  // |fuchsia::modular::BaseShell|
  void GetAuthenticationUIContext(
      fidl::InterfaceRequest<
          fuchsia::auth::AuthenticationUIContext> /*request*/) override {
    FXL_LOG(INFO)
        << "fuchsia::modular::BaseShell::GetAuthenticationUIContext() is"
           " unimplemented.";
  }

  // |fuchsia::modular::UserWatcher|
  void OnLogout() override {
    FXL_LOG(INFO) << "fuchsia::modular::UserWatcher::OnLogout()";
    base_shell_context_->Shutdown();
  }

  void Login(const std::string& account_id) {
    fuchsia::modular::UserLoginParams params;
    params.account_id = account_id;
    params.view_token = std::move(view_token_);
    params.user_controller = user_controller_.NewRequest();
    user_provider_->Login(std::move(params));
    user_controller_->Watch(user_watcher_binding_.NewBinding());
  }

  void Connect() {
    if (user_provider_ && view_token_) {
      if (settings_.user.empty()) {
        // Incognito mode.
        Login("");
        return;
      }

      user_provider_->PreviousUsers(
          [this](fidl::VectorPtr<fuchsia::modular::auth::Account> accounts) {
            FXL_LOG(INFO) << "Found " << accounts->size()
                          << " users in the user "
                          << "database";

            // Not running in incognito mode. Add the user if not already
            // added.
            std::string account_id;
            for (const auto& account : *accounts) {
              FXL_LOG(INFO) << "Found user " << account.display_name;
              if (account.display_name->size() >= settings_.user.size() &&
                  account.display_name->substr(0, settings_.user.size()) ==
                      settings_.user) {
                account_id = account.id;
                break;
              }
            }
            if (account_id.empty()) {
              user_provider_->AddUser(
                  fuchsia::modular::auth::IdentityProvider::DEV,
                  [this](fuchsia::modular::auth::AccountPtr account,
                         fidl::StringPtr status) { Login(account->id); });
            } else {
              Login(account_id);
            }
          });
    }
  }

  const Settings settings_;
  fidl::Binding<fuchsia::modular::UserWatcher> user_watcher_binding_;
  fuchsia::modular::BaseShellContextPtr base_shell_context_;
  fuchsia::modular::UserControllerPtr user_controller_;
  fuchsia::modular::UserProviderPtr user_provider_;
  zx::eventpair view_token_;
  fxl::WeakPtrFactory<DevBaseShellApp> weak_ptr_factory_;
  FXL_DISALLOW_COPY_AND_ASSIGN(DevBaseShellApp);
};

}  // namespace modular

int main(int argc, const char** argv) {
  auto command_line = fxl::CommandLineFromArgcArgv(argc, argv);
  modular::Settings settings(command_line);

  async::Loop loop(&kAsyncLoopConfigAttachToThread);

  auto context = component::StartupContext::CreateFromStartupInfo();
  modular::AppDriver<modular::DevBaseShellApp> driver(
      context->outgoing().deprecated_services(),
      std::make_unique<modular::DevBaseShellApp>(context.get(), settings),
      [&loop] { loop.Quit(); });

  loop.Run();
  return 0;
}
