// 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 "src/lib/intl/intl_property_provider_impl/intl_property_provider_impl.h"

#include <fuchsia/intl/cpp/fidl.h>
#include <fuchsia/settings/cpp/fidl.h>
#include <fuchsia/settings/cpp/fidl_test_base.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/gtest/real_loop_fixture.h>
#include <lib/sys/cpp/testing/component_context_provider.h>
#include <lib/syslog/cpp/log_settings.h>
#include <lib/syslog/cpp/macros.h>

#include "garnet/bin/trace/tests/component_context.h"
#include "lib/fostr/fidl/fuchsia/intl/formatting.h"
#include "lib/fostr/fidl/fuchsia/settings/formatting.h"
#include "src/lib/fidl_fuchsia_intl_ext/cpp/fidl_ext.h"
#include "src/lib/fxl/test/test_settings.h"
#include "src/modular/lib/fidl/clone.h"

namespace intl {
namespace testing {
namespace {

using fuchsia::intl::CalendarId;
using fuchsia::intl::LocaleId;
using fuchsia::intl::Profile;
using fuchsia::intl::PropertyProvider;
using fuchsia::intl::TemperatureUnit;
using fuchsia::intl::TimeZoneId;
using fuchsia::settings::HourCycle;
using sys::testing::ComponentContextProvider;

fuchsia::settings::IntlSettings NewSettings(std::vector<std::string> locale_ids,
                                            HourCycle hour_cycle,
                                            TemperatureUnit temperature_unit) {
  EXPECT_FALSE(locale_ids.empty()) << "by settings protocol locale ids must be nonempty";
  fuchsia::settings::IntlSettings settings;
  std::vector<LocaleId> locales;
  for (const auto& locale_id : locale_ids) {
    locales.emplace_back(LocaleId{
        .id = locale_id,
    });
  }
  settings.set_locales(std::move(locales));
  settings.set_temperature_unit(temperature_unit);
  settings.set_hour_cycle(hour_cycle);
  return settings;
}

// A fake implementation of fuchsia.settings.Intl service.  The Watch protocol specifically is not
// implemented correctly for multiple watchers.
class FakeSettingsService : public fuchsia::settings::testing::Intl_TestBase {
 public:
  FakeSettingsService()
      : intl_settings_(NewSettings({"en-US"}, HourCycle::H12, TemperatureUnit::FAHRENHEIT)),
        state_changed_(true) {}

  fidl::InterfaceRequestHandler<fuchsia::settings::Intl> GetHandler(
      async_dispatcher_t* dispatcher = nullptr) {
    return bindings_.GetHandler(static_cast<fuchsia::settings::Intl*>(this), dispatcher);
  }

  // Test method, used to modify the timezone identifier served by the fake setui service.
  void SetTimeZone(const std::string& iana_tz_id) {
    fuchsia::settings::IntlSettings new_settings = modular::CloneStruct(intl_settings_);
    new_settings.mutable_time_zone_id()->id = iana_tz_id;
    SetIntl(new_settings);
  }

  // Test method, used to modify the fake intl data that this fake service implementation will
  // serve.
  void SetIntl(const fuchsia::settings::IntlSettings& intl_settings) {
    if (fidl::Equals(intl_settings_, intl_settings)) {
      return;
    }
    intl_settings_ = modular::CloneStruct(intl_settings);
    state_changed_ = true;
    Notify();
  }

  // Implements `fuchsia.settings.Watch`, but only for a single watcher.
  void Watch(WatchCallback callback) override {
    watcher_ = std::move(callback);
    if (state_changed_) {
      Notify();
    }
  }

  // Called on all other methods that this fake does not implement.
  void NotImplemented_(const std::string& name) override {
    FAIL() << "Method not implemented: " << name;
  }

 private:
  void Notify() {
    if (watcher_ == nullptr) {
      FX_LOGS(INFO) << "No watcher, not notifying.";
      return;
    }
    FX_LOGS(INFO) << "telling watcher it's " << intl_settings_;
    watcher_(modular::CloneStruct(intl_settings_));
    state_changed_ = false;
    watcher_ = nullptr;
  }

  // The server-side connection for Intl service
  fidl::BindingSet<fuchsia::settings::Intl> bindings_;

  // The fake implementation of the watch protocol works for one listener only.
  WatchCallback watcher_;

  // Settings reported on a Watch call.
  fuchsia::settings::IntlSettings intl_settings_;

  // If set, it means that any incoming watch should return immediately.
  bool state_changed_;
};

// Tests for `IntlPropertyProviderImpl`.
class IntlPropertyProviderImplTest : public gtest::RealLoopFixture {
 protected:
  void SetUp() override {
    SetUpInstanceWithIncomingServices();
    PublishOutgoingService();
  }

  // Creates a server under test, connecting to the backend FIDL services that
  // are exposed by the test fixture.
  void SetUpInstanceWithIncomingServices() {
    setui_service_ = std::make_unique<FakeSettingsService>();
    ASSERT_EQ(ZX_OK, provider_.service_directory_provider()->AddService(
                         setui_service_->GetHandler(dispatcher())));
    fuchsia::settings::IntlPtr client =
        provider_.context()->svc()->Connect<fuchsia::settings::Intl>();
    instance_ = std::make_unique<IntlPropertyProviderImpl>(std::move(client));
  }

  // Makes the service of the unit under test available in the outgoing testing
  // directory, so that the tests can connect to it.
  void PublishOutgoingService() {
    ASSERT_EQ(ZX_OK, provider_.context()->outgoing()->AddPublicService(
                         instance_->GetHandler(dispatcher())));
  }

  // Creates a client of `fuchsia.intl.PropertyProvider`, which can be instantiated in a test case
  // to connect to the service under test.
  fuchsia::intl::PropertyProviderPtr GetClient() {
    return provider_.ConnectToPublicService<fuchsia::intl::PropertyProvider>();
  }

  // The default component context provider.
  ComponentContextProvider provider_;

  // The fake setui service instance.
  std::unique_ptr<FakeSettingsService> setui_service_;

  // The instance of the server under test.
  std::unique_ptr<IntlPropertyProviderImpl> instance_;
};

TEST_F(IntlPropertyProviderImplTest, GeneratesValidProfileFromDefaults) {
  setui_service_->SetTimeZone("America/New_York");

  Profile expected{};
  expected.set_locales({LocaleId{.id = "en-US-u"
                                       "-ca-gregory"
                                       "-fw-sun"
                                       "-hc-h12"
                                       "-ms-ussystem"
                                       "-nu-latn"
                                       "-tz-usnyc"}});
  expected.set_calendars({{CalendarId{.id = "und-u-ca-gregory"}}});
  expected.set_time_zones({TimeZoneId{.id = "America/New_York"}});
  expected.set_temperature_unit(TemperatureUnit::FAHRENHEIT);

  auto client = GetClient();

  Profile actual;
  client->GetProfile([&](Profile profile) { actual = std::move(profile); });
  RunLoopUntilIdle();
  EXPECT_EQ(expected, actual);
}

TEST_F(IntlPropertyProviderImplTest, NotifiesOnTimeZoneChange) {
  setui_service_->SetTimeZone("America/New_York");

  Profile expected_a{};
  expected_a.set_locales({LocaleId{.id = "en-US-u"
                                         "-ca-gregory"
                                         "-fw-sun"
                                         "-hc-h12"
                                         "-ms-ussystem"
                                         "-nu-latn"
                                         "-tz-usnyc"}});
  expected_a.set_calendars({{CalendarId{.id = "und-u-ca-gregory"}}});
  expected_a.set_time_zones({TimeZoneId{.id = "America/New_York"}});
  expected_a.set_temperature_unit(TemperatureUnit::FAHRENHEIT);

  auto client = GetClient();

  Profile actual;
  client->GetProfile([&](Profile profile) { actual = std::move(profile); });
  RunLoopUntilIdle();
  ASSERT_EQ(expected_a, actual);

  bool changed = false;
  client.events().OnChange = [&]() { changed = true; };
  RunLoopUntilIdle();
  ASSERT_FALSE(changed);

  setui_service_->SetTimeZone("Asia/Shanghai");
  RunLoopUntilIdle();
  ASSERT_TRUE(changed);

  Profile expected_b{};
  expected_b.set_locales({LocaleId{.id = "en-US-u"
                                         "-ca-gregory"
                                         "-fw-sun"
                                         "-hc-h12"
                                         "-ms-ussystem"
                                         "-nu-latn"
                                         "-tz-cnsha"}});
  expected_b.set_calendars({{CalendarId{.id = "und-u-ca-gregory"}}});
  expected_b.set_time_zones({TimeZoneId{.id = "Asia/Shanghai"}});
  expected_b.set_temperature_unit(TemperatureUnit::FAHRENHEIT);

  client->GetProfile([&](Profile profile) { actual = std::move(profile); });
  RunLoopUntilIdle();
  EXPECT_EQ(expected_b, actual);
}

TEST_F(IntlPropertyProviderImplTest, NotifiesOnLocaleChange) {
  setui_service_->SetIntl(NewSettings({"nl-NL"}, HourCycle::H12, TemperatureUnit::CELSIUS));
  setui_service_->SetTimeZone("UTC");
  RunLoopUntilIdle();

  Profile expected_a{};
  expected_a.set_locales({LocaleId{.id = "nl-NL-u"
                                         "-ca-gregory"
                                         "-fw-mon"
                                         "-hc-h12"
                                         "-ms-metric"
                                         "-nu-latn"
                                         "-tz-utc"}});
  expected_a.set_calendars({{CalendarId{.id = "und-u-ca-gregory"}}});
  expected_a.set_time_zones({TimeZoneId{.id = "UTC"}});
  expected_a.set_temperature_unit(TemperatureUnit::CELSIUS);

  auto client = GetClient();

  Profile actual;
  client->GetProfile([&](Profile profile) { actual = std::move(profile); });
  RunLoopUntilIdle();
  ASSERT_EQ(expected_a, actual);

  bool changed = false;
  client.events().OnChange = [&]() { changed = true; };
  RunLoopUntilIdle();
  ASSERT_FALSE(changed);

  setui_service_->SetIntl(NewSettings({"ru-RU"}, HourCycle::H23, TemperatureUnit::CELSIUS));
  RunLoopUntilIdle();
  ASSERT_TRUE(changed);

  Profile expected_b{};
  expected_b.set_locales({LocaleId{.id = "ru-RU-u"
                                         "-ca-gregory"
                                         "-fw-mon"
                                         "-hc-h23"
                                         "-ms-metric"
                                         "-nu-latn"
                                         "-tz-utc"}});
  expected_b.set_calendars({{CalendarId{.id = "und-u-ca-gregory"}}});
  expected_b.set_time_zones({TimeZoneId{.id = "UTC"}});
  expected_b.set_temperature_unit(TemperatureUnit::CELSIUS);

  client->GetProfile([&](Profile profile) { actual = std::move(profile); });
  RunLoopUntilIdle();
  EXPECT_EQ(expected_b, actual);
}

TEST_F(IntlPropertyProviderImplTest, SettingMix) {
  setui_service_->SetIntl(NewSettings({"nl-NL"}, HourCycle::H12, TemperatureUnit::CELSIUS));
  setui_service_->SetTimeZone("Europe/Amsterdam");
  RunLoopUntilIdle();

  auto client = GetClient();

  Profile actual;
  client->GetProfile([&](Profile profile) { actual = std::move(profile); });
  RunLoopUntilIdle();

  Profile expected{};
  expected.set_locales({LocaleId{.id = "nl-NL-u"
                                       "-ca-gregory"
                                       "-fw-mon"
                                       "-hc-h12"
                                       "-ms-metric"
                                       "-nu-latn"
                                       "-tz-nlams"}});
  expected.set_calendars({{CalendarId{.id = "und-u-ca-gregory"}}});
  expected.set_time_zones({TimeZoneId{.id = "Europe/Amsterdam"}});
  expected.set_temperature_unit(TemperatureUnit::CELSIUS);

  EXPECT_EQ(expected, actual);

  setui_service_->SetIntl(NewSettings({"nl-NL"}, HourCycle::H23, TemperatureUnit::CELSIUS));
  RunLoopUntilIdle();

  client->GetProfile([&](Profile profile) { actual = std::move(profile); });
  RunLoopUntilIdle();

  expected.set_locales({LocaleId{.id = "nl-NL-u"
                                       "-ca-gregory"
                                       "-fw-mon"
                                       "-hc-h23"
                                       "-ms-metric"
                                       "-nu-latn"
                                       "-tz-nlams"}});
  expected.set_calendars({{CalendarId{.id = "und-u-ca-gregory"}}});
  expected.set_time_zones({TimeZoneId{.id = "Europe/Amsterdam"}});
  expected.set_temperature_unit(TemperatureUnit::CELSIUS);

  EXPECT_EQ(expected, actual);
}

TEST_F(IntlPropertyProviderImplTest, Multilocale) {
  setui_service_->SetIntl(
      NewSettings({"nl-NL", "nl-BE", "nl", "fr-FR"}, HourCycle::H12, TemperatureUnit::CELSIUS));
  setui_service_->SetTimeZone("Europe/Amsterdam");
  RunLoopUntilIdle();

  auto client = GetClient();

  Profile actual;
  client->GetProfile([&](Profile profile) { actual = std::move(profile); });
  RunLoopUntilIdle();

  Profile expected{};
  expected.set_locales({
      LocaleId{.id = "nl-NL-u-ca-gregory-fw-mon-hc-h12-ms-metric-nu-latn-tz-nlams"},
      LocaleId{.id = "nl-BE-u-ca-gregory-fw-mon-hc-h12-ms-metric-nu-latn-tz-nlams"},
      LocaleId{.id = "nl-u-ca-gregory-fw-mon-hc-h12-ms-metric-nu-latn-tz-nlams"},
      LocaleId{.id = "fr-FR-u-ca-gregory-fw-mon-hc-h12-ms-metric-nu-latn-tz-nlams"},
  });
  expected.set_calendars({{CalendarId{.id = "und-u-ca-gregory"}}});
  expected.set_time_zones({TimeZoneId{.id = "Europe/Amsterdam"}});
  expected.set_temperature_unit(TemperatureUnit::CELSIUS);

  EXPECT_EQ(expected, actual);
}

}  // namespace
}  // namespace testing
}  // namespace intl

// This test has its own main because we want the logger to be turned on.
int main(int argc, char** argv) {
  if (!fxl::SetTestSettings(argc, argv)) {
    FX_LOGS(ERROR) << "Failed to parse log settings from command-line";
    return EXIT_FAILURE;
  }

  testing::InitGoogleTest(&argc, argv);

  tracing::test::InitComponentContext();

  return RUN_ALL_TESTS();
}
