// 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 "src/cobalt/bin/app/activity_listener_impl.h"

#include <fuchsia/ui/activity/cpp/fidl.h>
#include <lib/gtest/test_loop_fixture.h>

#include <cstdio>

#include <gtest/gtest.h>

#include "sdk/lib/sys/cpp/testing/service_directory_provider.h"
#include "src/lib/testing/loop_fixture/test_loop_fixture.h"

namespace cobalt {

using fuchsia::ui::activity::State;
namespace activity = fuchsia::ui::activity;

class FakeActivity : public activity::Provider {
 public:
  fidl::InterfaceRequestHandler<activity::Provider> GetHandler() {
    return [this](fidl::InterfaceRequest<activity::Provider> request) {
      binding_ = std::make_unique<fidl::Binding<activity::Provider>>(this, std::move(request));
    };
  }

  void WatchState(::fidl::InterfaceHandle<class activity::Listener> listener) override {
    listener_ = listener.Bind();
    SendUpdate();
  }

  void SetState(activity::State state) {
    state_ = state;
    SendUpdate();
  }

  void CloseConnection() {
    if (binding_) {
      binding_->Unbind();
    }
  }

 private:
  void SendUpdate() {
    listener_->OnStateChanged(state_, 0, []() {});
  }

  std::unique_ptr<fidl::Binding<fuchsia::ui::activity::Provider>> binding_;
  ::fidl::InterfacePtr<fuchsia::ui::activity::Listener> listener_;
  activity::State state_ = activity::State::UNKNOWN;
};
class ActivityListenerTest : public gtest::TestLoopFixture,
                             public testing::WithParamInterface<std::optional<bool>> {
 public:
  ActivityListenerTest() : service_directory_provider_(dispatcher()) {}

  void SetUp() override {
    activity_service_ = std::make_unique<FakeActivity>();
    service_directory_provider_.AddService(activity_service_->GetHandler());

    listener_ = std::make_unique<ActivityListenerImpl>(
        dispatcher(), service_directory_provider_.service_directory());
    listener_->Start([this](ActivityState state) { Callback(state); });
    RunLoopUntilIdle();
  }

  void Reconnect() { service_directory_provider_.AddService(activity_service_->GetHandler()); }

  void Callback(ActivityState state) { current_state_ = state; }

 protected:
  sys::testing::ServiceDirectoryProvider service_directory_provider_;
  std::unique_ptr<FakeActivity> activity_service_;
  std::unique_ptr<ActivityListenerImpl> listener_;
  ActivityState current_state_;
};

TEST_F(ActivityListenerTest, DefaultsToStateUnknown) {
  EXPECT_TRUE(listener_->IsConnected());
  EXPECT_EQ(current_state_, ActivityState::UNKNOWN);
  EXPECT_EQ(listener_->state(), ActivityState::UNKNOWN);
}

TEST_F(ActivityListenerTest, InvokesCallbackWithCorrectState) {
  activity_service_->SetState(fuchsia::ui::activity::State::ACTIVE);
  RunLoopUntilIdle();
  EXPECT_EQ(current_state_, ActivityState::ACTIVE);
  EXPECT_EQ(listener_->state(), ActivityState::ACTIVE);

  activity_service_->SetState(fuchsia::ui::activity::State::IDLE);
  RunLoopUntilIdle();
  EXPECT_EQ(current_state_, ActivityState::IDLE);
  EXPECT_EQ(listener_->state(), ActivityState::IDLE);

  activity_service_->SetState(fuchsia::ui::activity::State::UNKNOWN);
  RunLoopUntilIdle();
  EXPECT_EQ(current_state_, ActivityState::UNKNOWN);
  EXPECT_EQ(listener_->state(), ActivityState::UNKNOWN);
}

TEST_F(ActivityListenerTest, StateResetIfServerNotAvailable) {
  current_state_ = ActivityState::IDLE;

  activity_service_->CloseConnection();
  RunLoopUntilIdle();

  EXPECT_EQ(current_state_, ActivityState::UNKNOWN);
  EXPECT_EQ(listener_->state(), ActivityState::UNKNOWN);
}

TEST_F(ActivityListenerTest, OverridesCallback) {
  activity_service_->SetState(fuchsia::ui::activity::State::ACTIVE);
  RunLoopUntilIdle();
  EXPECT_EQ(current_state_, ActivityState::ACTIVE);
  EXPECT_EQ(listener_->state(), ActivityState::ACTIVE);

  listener_->Start([](ActivityState state) {});
  activity_service_->SetState(fuchsia::ui::activity::State::UNKNOWN);
  RunLoopUntilIdle();
  EXPECT_EQ(current_state_, ActivityState::ACTIVE);
  EXPECT_EQ(listener_->state(), ActivityState::UNKNOWN);

  activity_service_->SetState(fuchsia::ui::activity::State::IDLE);
  listener_->Start([this](ActivityState state) { Callback(state); });
  RunLoopUntilIdle();
  EXPECT_EQ(current_state_, ActivityState::IDLE);
  EXPECT_EQ(listener_->state(), ActivityState::IDLE);
}

TEST_F(ActivityListenerTest, ReconnectsIfServerClosesConnection) {
  activity_service_->CloseConnection();
  activity_service_->SetState(fuchsia::ui::activity::State::ACTIVE);
  EXPECT_EQ(current_state_, ActivityState::UNKNOWN);
  EXPECT_EQ(listener_->state(), ActivityState::UNKNOWN);

  Reconnect();
  RunLoopFor(zx::msec(200));
  EXPECT_EQ(current_state_, ActivityState::ACTIVE);
  EXPECT_EQ(listener_->state(), ActivityState::ACTIVE);
}

}  // namespace cobalt
