// Copyright 2018 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/ui/a11y/bin/a11y_manager/app.h"

#include <lib/syslog/cpp/macros.h>
#include <zircon/status.h>

#include "src/ui/a11y/lib/screen_reader/focus/a11y_focus_manager_impl.h"
#include "src/ui/a11y/lib/screen_reader/screen_reader_context.h"
#include "src/ui/a11y/lib/util/util.h"
#include "src/ui/a11y/lib/view/view_coordinate_converter.h"

namespace {

template <typename T>
auto to_underlying(T value) {
  return static_cast<std::underlying_type_t<T>>(value);
}

}  // namespace

namespace a11y_manager {

void A11yManagerInitializationState ::SetI18nProfileReady() {
  has_i18N_profile_ = true;
  if (IsInitialized() && callback_) {
    callback_();
  }
}

void A11yManagerInitializationState ::SetA11yViewReady() {
  is_a11y_view_initialized_ = true;
  if (IsInitialized() && callback_) {
    callback_();
  }
}

App::App(sys::ComponentContext* context, a11y::ViewManager* view_manager,
         a11y::TtsManager* tts_manager, a11y::ColorTransformManager* color_transform_manager,
         a11y::GestureListenerRegistry* gesture_listener_registry,
         a11y::BootInfoManager* boot_info_manager,
         a11y::ScreenReaderContextFactory* screen_reader_context_factory,
         inspect::Node inspect_node)
    : context_(context),
      view_manager_(view_manager),
      tts_manager_(tts_manager),
      color_transform_manager_(color_transform_manager),
      gesture_listener_registry_(gesture_listener_registry),
      screen_reader_context_factory_(screen_reader_context_factory),
      inspect_node_(std::move(inspect_node)),
      inspect_property_intl_property_provider_disconnected_(
          inspect_node_.CreateBool(kIntlPropertyProviderDisconnectedInspectName, false)),
      screen_reader_enabled_(inspect_node_.CreateBool(kScreenReaderEnabledInspectName,
                                                      state_.screen_reader_enabled())),
      magnifier_enabled_(
          inspect_node_.CreateBool(kMagnifierEnabledInspectName, state_.magnifier_enabled())),
      color_inversion_enabled_(inspect_node_.CreateBool(kColorInversionEnabledInspectName,
                                                        state_.color_inversion_enabled())),
      color_correction_mode_(inspect_node_.CreateUint(
          kColorCorrectionModeInspectName, to_underlying(state_.color_correction_mode()))) {
  FX_DCHECK(context);
  FX_DCHECK(view_manager);
  FX_DCHECK(tts_manager);
  FX_DCHECK(color_transform_manager);
  FX_DCHECK(gesture_listener_registry_);
  FX_DCHECK(boot_info_manager);

  // The screen reader should announce that it is on at boot iff the boot was
  // user-initiated.
  state_.set_announce_screen_reader_enabled(boot_info_manager->LastRebootWasUserInitiated());

  context->outgoing()->AddPublicService(semantics_manager_bindings_.GetHandler(view_manager_));
  context->outgoing()->AddPublicService(
      virtualkeyboard_registry_bindings_.GetHandler(view_manager_));
  context->outgoing()->AddPublicService(
      gesture_listener_registry_bindings_.GetHandler(gesture_listener_registry_));

  auto magnifier_delegate =
      std::static_pointer_cast<a11y::Magnifier2::Delegate>(view_manager->flatland_a11y_view());
  FX_CHECK(magnifier_delegate);
  magnifier_ = std::make_unique<a11y::Magnifier2>(magnifier_delegate);

  // Inits Focus Chain focuser support / listening Focus Chain updates.
  focus_chain_manager_ = std::make_unique<a11y::FocusChainManager>(view_manager_->a11y_view());

  // |focus_chain_manager_| listens for Focus Chain updates. Connects to the listener registry and
  // start listening.
  fuchsia::ui::focus::FocusChainListenerRegistryPtr focus_chain_listener_registry =
      context->svc()->Connect<fuchsia::ui::focus::FocusChainListenerRegistry>();
  focus_chain_listener_registry.set_error_handler([](zx_status_t status) {
    FX_LOGS(ERROR) << "Error from fuchsia::ui::focus::FocusChainListenerRegistry: "
                   << zx_status_get_string(status);
  });
  auto focus_chain_listener_handle =
      focus_chain_listener_bindings_.AddBinding(focus_chain_manager_.get());
  focus_chain_listener_registry->Register(focus_chain_listener_handle.Bind());

  // Connect to setui.
  setui_settings_ = context->svc()->Connect<fuchsia::settings::Accessibility>();
  setui_settings_.set_error_handler([](zx_status_t status) {
    FX_LOGS(ERROR) << "Error from fuchsia::settings::Accessibility: "
                   << zx_status_get_string(status);
  });

  initialization_state_.SetOnA11yManagerInitializedCallback([this]() { FinishSetUp(); });

  // Connects to property provider to retrieve the current locale. Also adds a handler for the event
  // to process when the locale changes.
  property_provider_ = context->svc()->Connect<fuchsia::intl::PropertyProvider>();
  property_provider_.set_error_handler([this](zx_status_t status) {
    FX_LOGS(INFO) << "Error from fuchsia::intl::PropertyProvider: " << zx_status_get_string(status);
    if (status == ZX_ERR_PEER_CLOSED) {
      FX_LOGS(INFO) << "Using the default locale: en-US";
      inspect_property_intl_property_provider_disconnected_.Set(true);
      fuchsia::intl::Profile default_profile;
      this->i18n_profile_ = std::move(default_profile);
      this->i18n_profile_->mutable_locales()->push_back({.id = "en-US"});
      if (!this->initialization_state_.IsInitialized()) {
        this->initialization_state_.SetI18nProfileReady();
      }
    }
  });
  property_provider_.events().OnChange =
      fit::bind_member<&App::PropertyProviderOnChangeHandler>(this);
  // Fetches the initial locale.
  // When the locale is returned, marks this object as initialized and ready to process requests.
  // This is necessary because the Locale is a must-have information that needs to be present to
  // build some elements.
  property_provider_->GetProfile([this](fuchsia::intl::Profile profile) mutable {
    this->i18n_profile_ = std::move(profile);
    if (!this->initialization_state_.IsInitialized()) {
      this->initialization_state_.SetI18nProfileReady();
    }
  });

  auto a11y_view = view_manager_->a11y_view();
  FX_DCHECK(a11y_view);
  a11y_view->add_scene_ready_callback([this]() {
    this->initialization_state_.SetA11yViewReady();
    return true;
  });
}

App::~App() = default;

void App::FinishSetUp() {
  FX_DCHECK(initialization_state_.IsInitialized());
  FX_DCHECK(i18n_profile_) << "App is being initialized without i18n profile from user.";

  // Configures a View Coordinate Converter. Done at this point because the a11y view is guaranteed
  // to be initialized.
  auto a11y_view = view_manager_->a11y_view();
  FX_DCHECK(a11y_view);
  auto view_ref = a11y_view->view_ref();
  FX_DCHECK(view_ref);
  auto view_ref_koid = a11y::GetKoid(*view_ref);
  auto view_coordinate_converter = std::make_unique<a11y::ViewCoordinateConverter>(
      context_->svc()->Connect<fuchsia::ui::observation::scope::Registry>(), view_ref_koid);
  view_manager_->SetViewCoordinateConverter(std::move(view_coordinate_converter));

  // Note that initializing the gesture manager here is important:
  // 1. It is done when the a11y view is initialized for sure;
  // 2. It obtains the touch source, and starts watching for pointer events, even when a11y features
  // are not on. This is **critical**: a11y may block touch input if it does not start participating
  // right away in gesture disambiguation.
  gesture_manager_ = std::make_unique<a11y::GestureManagerV2>(a11y_view->TakeTouchSource());

  // Start watching setui for current settings. Must be the last step in the initialization because
  // this may turn on / off a11y features, and these features depend on the things initialized
  // above.
  WatchSetui();
}

void App::SetState(A11yManagerState state) {
  state_ = state;
  UpdateScreenReaderState();
  UpdateMagnifierState();
  UpdateColorTransformState();
  // May rely on screen reader existence.
  UpdateGestureManagerState();
  UpdateInspectState();

  // The first call to SetState() will set the screen reader enabled setting to its
  // value at boot time. This first call to SetState() should result in screen
  // reader output iff the screen reader is enabled at boot AND the boot is
  // user-initiated. Once this initial value has been set, all subsequent
  // enables of the screen reader should be announced.
  state_.set_announce_screen_reader_enabled(true);
}

void App::UpdateScreenReaderState() {
  // If this is used elsewhere, it should be moved into its own function.
  view_manager_->SetSemanticsEnabled(state_.screen_reader_enabled());

  if (state_.screen_reader_enabled()) {
    if (!screen_reader_) {
      screen_reader_ = InitializeScreenReader();
    }
  } else {
    screen_reader_.reset();
  }
}

void App::UpdateMagnifierState() {
  if (!state_.magnifier_enabled()) {
    magnifier_->ZoomOutIfMagnified();
  }
}

void App::UpdateColorTransformState() {
  bool color_inversion = state_.color_inversion_enabled();
  fuchsia::accessibility::ColorCorrectionMode color_blindness_type = state_.color_correction_mode();
  color_transform_manager_->ChangeColorTransform(color_inversion, color_blindness_type);
}

void App::UpdateGestureManagerState() {
  GestureState new_state = {.screen_reader_gestures = state_.screen_reader_enabled(),
                            .magnifier_gestures = state_.magnifier_enabled()};

  if (new_state == gesture_state_)
    return;

  gesture_state_ = new_state;

  // For now the easiest way to properly set up all gestures with the right priorities is to clear
  // the gesture manager when the gestures change.
  gesture_manager_->Clear();

  if (!gesture_state_.has_any()) {
    return;
  }

  // The ordering of these recognizers is significant, as it signifies priority.
  if (gesture_state_.magnifier_gestures) {
    magnifier_->BindGestures(gesture_manager_->gesture_handler());
  }

  if (gesture_state_.screen_reader_gestures) {
    screen_reader_->BindGestures(gesture_manager_->gesture_handler());
    gesture_manager_->gesture_handler()->ConsumeAll();
  }
}

void App::UpdateInspectState() {
  screen_reader_enabled_.Set(state_.screen_reader_enabled());
  magnifier_enabled_.Set(state_.magnifier_enabled());
  color_inversion_enabled_.Set(state_.color_inversion_enabled());
  color_correction_mode_.Set(to_underlying(state_.color_correction_mode()));
}

bool App::GestureState::operator==(GestureState o) const {
  return screen_reader_gestures == o.screen_reader_gestures &&
         magnifier_gestures == o.magnifier_gestures;
}

void App::SetuiWatchCallback(fuchsia::settings::AccessibilitySettings settings) {
  SetState(state_.withSettings(settings));
  WatchSetui();
}

void App::WatchSetui() { setui_settings_->Watch(fit::bind_member<&App::SetuiWatchCallback>(this)); }

// Converts setui color blindess type to the relevant accessibility color correction mode.
fuchsia::accessibility::ColorCorrectionMode ConvertColorCorrection(
    fuchsia::settings::ColorBlindnessType color_blindness_type) {
  switch (color_blindness_type) {
    case fuchsia::settings::ColorBlindnessType::PROTANOMALY:
      return fuchsia::accessibility::ColorCorrectionMode::CORRECT_PROTANOMALY;
    case fuchsia::settings::ColorBlindnessType::DEUTERANOMALY:
      return fuchsia::accessibility::ColorCorrectionMode::CORRECT_DEUTERANOMALY;

    case fuchsia::settings::ColorBlindnessType::TRITANOMALY:
      return fuchsia::accessibility::ColorCorrectionMode::CORRECT_TRITANOMALY;
    case fuchsia::settings::ColorBlindnessType::NONE:
    // fall through
    default:
      return fuchsia::accessibility::ColorCorrectionMode::DISABLED;
  }
}

A11yManagerState A11yManagerState::withSettings(
    const fuchsia::settings::AccessibilitySettings& systemSettings) {
  A11yManagerState state = *this;

  if (systemSettings.has_screen_reader()) {
    state.screen_reader_enabled_ = systemSettings.screen_reader();
  }

  if (systemSettings.has_enable_magnification()) {
    state.magnifier_enabled_ = systemSettings.enable_magnification();
  }

  if (systemSettings.has_color_inversion()) {
    state.color_inversion_enabled_ = systemSettings.color_inversion();
  }

  if (systemSettings.has_color_correction()) {
    state.color_correction_mode_ = ConvertColorCorrection(systemSettings.color_correction());
  }

  return state;
}

std::unique_ptr<a11y::ScreenReader> App::InitializeScreenReader() {
  auto a11y_focus_manager = std::make_unique<a11y::A11yFocusManagerImpl>(
      focus_chain_manager_.get(), focus_chain_manager_.get(), view_manager_, view_manager_,
      view_manager_->flatland_a11y_view(), inspect_node_.CreateChild("focus_manager"));
  std::string locale_id = "en-US";
  if (i18n_profile_ && i18n_profile_->has_locales() && !i18n_profile_->locales().empty()) {
    locale_id = i18n_profile_->locales()[0].id;
  }
  auto screen_reader_context = screen_reader_context_factory_->CreateScreenReaderContext(
      std::move(a11y_focus_manager), tts_manager_, view_manager_, locale_id);
  auto screen_reader = std::make_unique<a11y::ScreenReader>(
      std::move(screen_reader_context), view_manager_, view_manager_, gesture_listener_registry_,
      tts_manager_, state_.announce_screen_reader_enabled());
  view_manager_->GetSemanticsEventManager()->Register(
      screen_reader->GetSemanticsEventListenerWeakPtr());
  return screen_reader;
}

void App::PropertyProviderOnChangeHandler() {
  property_provider_->GetProfile([this](fuchsia::intl::Profile profile) {
    this->i18n_profile_ = std::move(profile);
    if (state_.screen_reader_enabled()) {
      // Reset screen_reader_ to force re-initialization.
      screen_reader_.reset();

      // Close the old engine connection.
      tts_manager_->CloseEngine();
      UpdateScreenReaderState();

      // Clear screen reader gesture state to force update.
      gesture_state_.screen_reader_gestures = false;
      UpdateGestureManagerState();
    }
  });
}

}  // namespace a11y_manager
