// Copyright 2016 The Chromium 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 "ui/views/mus/mus_client.h"

#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/ui/public/cpp/gpu/gpu.h"
#include "services/ui/public/cpp/input_devices/input_device_client.h"
#include "services/ui/public/cpp/property_type_converters.h"
#include "services/ui/public/interfaces/constants.mojom.h"
#include "services/ui/public/interfaces/window_manager.mojom.h"
#include "ui/aura/env.h"
#include "ui/aura/mus/capture_synchronizer.h"
#include "ui/aura/mus/mus_context_factory.h"
#include "ui/aura/mus/property_converter.h"
#include "ui/aura/mus/window_tree_client.h"
#include "ui/aura/mus/window_tree_host_mus.h"
#include "ui/aura/mus/window_tree_host_mus_init_params.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/mojo/clipboard_client.h"
#include "ui/views/mus/aura_init.h"
#include "ui/views/mus/ax_remote_host.h"
#include "ui/views/mus/desktop_window_tree_host_mus.h"
#include "ui/views/mus/mus_property_mirror.h"
#include "ui/views/mus/pointer_watcher_event_router.h"
#include "ui/views/mus/screen_mus.h"
#include "ui/views/views_delegate.h"
#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/wm/core/shadow_types.h"
#include "ui/wm/core/wm_state.h"

#if defined(USE_OZONE)
#include "ui/base/cursor/ozone/cursor_data_factory_ozone.h"
#endif

// Widget::InitParams::Type must match that of ui::mojom::WindowType.
#define WINDOW_TYPES_MATCH(NAME)                                      \
  static_assert(                                                      \
      static_cast<int32_t>(views::Widget::InitParams::TYPE_##NAME) == \
          static_cast<int32_t>(ui::mojom::WindowType::NAME),          \
      "Window type constants must match")

WINDOW_TYPES_MATCH(WINDOW);
WINDOW_TYPES_MATCH(PANEL);
WINDOW_TYPES_MATCH(WINDOW_FRAMELESS);
WINDOW_TYPES_MATCH(CONTROL);
WINDOW_TYPES_MATCH(POPUP);
WINDOW_TYPES_MATCH(MENU);
WINDOW_TYPES_MATCH(TOOLTIP);
WINDOW_TYPES_MATCH(BUBBLE);
WINDOW_TYPES_MATCH(DRAG);
// ui::mojom::WindowType::UNKNOWN does not correspond to a value in
// Widget::InitParams::Type.

namespace views {

// static
MusClient* MusClient::instance_ = nullptr;

MusClient::InitParams::InitParams() = default;

MusClient::InitParams::~InitParams() = default;

MusClient::MusClient(const InitParams& params) : identity_(params.identity) {
  DCHECK(!instance_);
  DCHECK(aura::Env::GetInstance());
  instance_ = this;

#if defined(USE_OZONE)
  // If we're in a mus client, we aren't going to have all of ozone initialized
  // even though we're in an ozone build. All the hard coded USE_OZONE ifdefs
  // that handle cursor code expect that there will be a CursorFactoryOzone
  // instance. Partially initialize the ozone cursor internals here, like we
  // partially initialize other ozone subsystems in
  // ChromeBrowserMainExtraPartsViews.
  if (params.create_cursor_factory)
    cursor_factory_ozone_ = std::make_unique<ui::CursorDataFactoryOzone>();
#endif

  property_converter_ = std::make_unique<aura::PropertyConverter>();
  property_converter_->RegisterPrimitiveProperty(
      ::wm::kShadowElevationKey,
      ui::mojom::WindowManager::kShadowElevation_Property,
      aura::PropertyConverter::CreateAcceptAnyValueCallback());

  if (params.create_wm_state)
    wm_state_ = std::make_unique<wm::WMState>();

  service_manager::Connector* connector = params.connector;

  if (!params.window_tree_client) {
    // If this process is running in the WindowService, then discardable memory
    // should have already been created.
    const bool create_discardable_memory = !params.running_in_ws_process;
    owned_window_tree_client_ =
        aura::WindowTreeClient::CreateForWindowTreeFactory(
            connector, this, create_discardable_memory,
            std::move(params.io_task_runner));
    window_tree_client_ = owned_window_tree_client_.get();
    aura::Env::GetInstance()->SetWindowTreeClient(window_tree_client_);
  } else {
    window_tree_client_ = params.window_tree_client;
  }

  pointer_watcher_event_router_ =
      std::make_unique<PointerWatcherEventRouter>(window_tree_client_);

  if (connector && !params.running_in_ws_process) {
    input_device_client_ = std::make_unique<ui::InputDeviceClient>();
    ui::mojom::InputDeviceServerPtr input_device_server;
    connector->BindInterface(ui::mojom::kServiceName, &input_device_server);
    input_device_client_->Connect(std::move(input_device_server));

    screen_ = std::make_unique<ScreenMus>(this);
    display::Screen::SetScreenInstance(screen_.get());

    // NOTE: this deadlocks if |running_in_ws_process| is true (because the main
    // thread is running the WindowService).
    window_tree_client_->WaitForDisplays();

    ui::mojom::ClipboardHostPtr clipboard_host_ptr;
    connector->BindInterface(ui::mojom::kServiceName, &clipboard_host_ptr);
    ui::Clipboard::SetClipboardForCurrentThread(
        std::make_unique<ui::ClipboardClient>(std::move(clipboard_host_ptr)));

    if (params.use_accessibility_host) {
      ax_remote_host_ = std::make_unique<AXRemoteHost>();
      ax_remote_host_->Init(connector);
    }
  }

  ViewsDelegate::GetInstance()->set_native_widget_factory(
      base::Bind(&MusClient::CreateNativeWidget, base::Unretained(this)));
  ViewsDelegate::GetInstance()->set_desktop_window_tree_host_factory(base::Bind(
      &MusClient::CreateDesktopWindowTreeHost, base::Unretained(this)));
}

MusClient::~MusClient() {
  // Tear down accessibility before WindowTreeClient to ensure window tree
  // cleanup doesn't trigger accessibility events.
  ax_remote_host_.reset();

  // ~WindowTreeClient calls back to us (we're its delegate), destroy it while
  // we are still valid.
  owned_window_tree_client_.reset();
  window_tree_client_ = nullptr;
  ui::OSExchangeDataProviderFactory::SetFactory(nullptr);
  ui::Clipboard::DestroyClipboardForCurrentThread();

  if (ViewsDelegate::GetInstance()) {
    ViewsDelegate::GetInstance()->set_native_widget_factory(
        ViewsDelegate::NativeWidgetFactory());
    ViewsDelegate::GetInstance()->set_desktop_window_tree_host_factory(
        ViewsDelegate::DesktopWindowTreeHostFactory());
  }

  if (screen_) {
    display::Screen::SetScreenInstance(nullptr);
    screen_.reset();
  }

  DCHECK_EQ(instance_, this);
  instance_ = nullptr;
  DCHECK(aura::Env::GetInstance());
}

// static
bool MusClient::ShouldCreateDesktopNativeWidgetAura(
    const Widget::InitParams& init_params) {
  const bool from_window_service =
      (init_params.context &&
       init_params.context->env()->mode() == aura::Env::Mode::LOCAL) ||
      (init_params.parent &&
       init_params.parent->env()->mode() == aura::Env::Mode::LOCAL);
  // |from_window_service| is true if the aura::Env has a mode of LOCAL. If
  // the mode is LOCAL there are two envs, one used by the window service
  // (LOCAL), and the other for non-window-service code. Windows created with
  // LOCAL should use NativeWidgetAura (which happens if false is returned
  // here).
  if (from_window_service)
    return false;

  // TYPE_CONTROL and child widgets require a NativeWidgetAura.
  return init_params.type != Widget::InitParams::TYPE_CONTROL &&
         !init_params.child;
}

// static
bool MusClient::ShouldMakeWidgetWindowsTranslucent(
    const Widget::InitParams& params) {
  // |TYPE_WINDOW| and |TYPE_PANEL| are forced to translucent so that the
  // window manager can draw the client decorations.
  return params.opacity == Widget::InitParams::TRANSLUCENT_WINDOW ||
         params.type == Widget::InitParams::TYPE_WINDOW ||
         params.type == Widget::InitParams::TYPE_PANEL;
}

// static
std::map<std::string, std::vector<uint8_t>>
MusClient::ConfigurePropertiesFromParams(
    const Widget::InitParams& init_params) {
  using PrimitiveType = aura::PropertyConverter::PrimitiveType;
  using WindowManager = ui::mojom::WindowManager;
  using TransportType = std::vector<uint8_t>;

  std::map<std::string, TransportType> properties = init_params.mus_properties;

  // Widget::InitParams::Type matches ui::mojom::WindowType.
  properties[WindowManager::kWindowType_InitProperty] =
      mojo::ConvertTo<TransportType>(static_cast<int32_t>(init_params.type));

  properties[WindowManager::kFocusable_InitProperty] =
      mojo::ConvertTo<TransportType>(init_params.CanActivate());

  properties[WindowManager::kTranslucent_InitProperty] =
      mojo::ConvertTo<TransportType>(
          ShouldMakeWidgetWindowsTranslucent(init_params));

  if (!init_params.bounds.IsEmpty()) {
    properties[WindowManager::kBounds_InitProperty] =
        mojo::ConvertTo<TransportType>(init_params.bounds);
  }

  if (!init_params.name.empty()) {
    properties[WindowManager::kName_Property] =
        mojo::ConvertTo<TransportType>(init_params.name);
  }

  properties[WindowManager::kAlwaysOnTop_Property] =
      mojo::ConvertTo<TransportType>(
          static_cast<PrimitiveType>(init_params.keep_on_top));

  properties[WindowManager::kRemoveStandardFrame_InitProperty] =
      mojo::ConvertTo<TransportType>(init_params.remove_standard_frame);

  if (init_params.corner_radius) {
    properties[WindowManager::kWindowCornerRadius_Property] =
        mojo::ConvertTo<TransportType>(
            static_cast<PrimitiveType>(*init_params.corner_radius));
  }

  if (!Widget::RequiresNonClientView(init_params.type))
    return properties;

  if (init_params.delegate) {
    if (properties.count(WindowManager::kResizeBehavior_Property) == 0) {
      properties[WindowManager::kResizeBehavior_Property] =
          mojo::ConvertTo<TransportType>(static_cast<PrimitiveType>(
              init_params.delegate->GetResizeBehavior()));
    }

    if (init_params.delegate->ShouldShowWindowTitle()) {
      properties[WindowManager::kWindowTitleShown_Property] =
          mojo::ConvertTo<TransportType>(static_cast<PrimitiveType>(
              init_params.delegate->ShouldShowWindowTitle()));
    }

    if (!init_params.delegate->GetWindowTitle().empty()) {
      properties[WindowManager::kWindowTitle_Property] =
          mojo::ConvertTo<TransportType>(
              init_params.delegate->GetWindowTitle());
    }

    // TODO(crbug.com/667566): Support additional scales or gfx::Image[Skia].
    gfx::ImageSkia app_icon = init_params.delegate->GetWindowAppIcon();
    SkBitmap app_bitmap = app_icon.GetRepresentation(1.f).sk_bitmap();
    if (!app_bitmap.isNull()) {
      properties[WindowManager::kAppIcon_Property] =
          mojo::ConvertTo<TransportType>(app_bitmap);
    }

    // TODO(crbug.com/667566): Support additional scales or gfx::Image[Skia].
    gfx::ImageSkia window_icon = init_params.delegate->GetWindowIcon();
    SkBitmap window_bitmap = window_icon.GetRepresentation(1.f).sk_bitmap();
    if (!window_bitmap.isNull()) {
      properties[WindowManager::kWindowIcon_Property] =
          mojo::ConvertTo<TransportType>(window_bitmap);
    }
  }

  return properties;
}

NativeWidget* MusClient::CreateNativeWidget(
    const Widget::InitParams& init_params,
    internal::NativeWidgetDelegate* delegate) {
  if (!ShouldCreateDesktopNativeWidgetAura(init_params)) {
    // A null return value results in creating NativeWidgetAura.
    return nullptr;
  }

  DesktopNativeWidgetAura* native_widget =
      new DesktopNativeWidgetAura(delegate);
  if (init_params.desktop_window_tree_host) {
    native_widget->SetDesktopWindowTreeHost(
        base::WrapUnique(init_params.desktop_window_tree_host));
  } else {
    native_widget->SetDesktopWindowTreeHost(
        CreateDesktopWindowTreeHost(init_params, delegate, native_widget));
  }
  return native_widget;
}

void MusClient::OnWidgetInitDone(Widget* widget) {
  // Start tracking the widget for accessibility.
  if (ax_remote_host_)
    ax_remote_host_->StartMonitoringWidget(widget);
}

void MusClient::OnCaptureClientSet(
    aura::client::CaptureClient* capture_client) {
  pointer_watcher_event_router_->AttachToCaptureClient(capture_client);
  window_tree_client_->capture_synchronizer()->AttachToCaptureClient(
      capture_client);
}

void MusClient::OnCaptureClientUnset(
    aura::client::CaptureClient* capture_client) {
  pointer_watcher_event_router_->DetachFromCaptureClient(capture_client);
  window_tree_client_->capture_synchronizer()->DetachFromCaptureClient(
      capture_client);
}

void MusClient::AddObserver(MusClientObserver* observer) {
  observer_list_.AddObserver(observer);
}

void MusClient::RemoveObserver(MusClientObserver* observer) {
  observer_list_.RemoveObserver(observer);
}

void MusClient::SetMusPropertyMirror(
    std::unique_ptr<MusPropertyMirror> mirror) {
  mus_property_mirror_ = std::move(mirror);
}

void MusClient::CloseAllWidgets() {
  for (aura::Window* root : window_tree_client_->GetRoots()) {
    Widget* widget = Widget::GetWidgetForNativeView(root);
    if (widget)
      widget->CloseNow();
  }
}

std::unique_ptr<DesktopWindowTreeHost> MusClient::CreateDesktopWindowTreeHost(
    const Widget::InitParams& init_params,
    internal::NativeWidgetDelegate* delegate,
    DesktopNativeWidgetAura* desktop_native_widget_aura) {
  std::map<std::string, std::vector<uint8_t>> mus_properties =
      ConfigurePropertiesFromParams(init_params);
  aura::WindowTreeHostMusInitParams window_tree_host_init_params =
      aura::CreateInitParamsForTopLevel(MusClient::Get()->window_tree_client(),
                                        std::move(mus_properties));
  return std::make_unique<DesktopWindowTreeHostMus>(
      std::move(window_tree_host_init_params), delegate,
      desktop_native_widget_aura);
}

void MusClient::OnEmbed(
    std::unique_ptr<aura::WindowTreeHostMus> window_tree_host) {
  NOTREACHED();
}

void MusClient::OnLostConnection(aura::WindowTreeClient* client) {}

void MusClient::OnEmbedRootDestroyed(
    aura::WindowTreeHostMus* window_tree_host) {
  static_cast<DesktopWindowTreeHostMus*>(window_tree_host)
      ->ServerDestroyedWindow();
}

void MusClient::OnPointerEventObserved(const ui::PointerEvent& event,
                                       int64_t display_id,
                                       aura::Window* target) {
  pointer_watcher_event_router_->OnPointerEventObserved(event, display_id,
                                                        target);
}

void MusClient::OnDisplaysChanged(
    std::vector<ui::mojom::WsDisplayPtr> ws_displays,
    int64_t primary_display_id,
    int64_t internal_display_id,
    int64_t display_id_for_new_windows) {
  if (screen_) {
    screen_->OnDisplaysChanged(std::move(ws_displays), primary_display_id,
                               internal_display_id, display_id_for_new_windows);
  }
}

void MusClient::OnWindowManagerFrameValuesChanged() {
  for (auto& observer : observer_list_)
    observer.OnWindowManagerFrameValuesChanged();
}

aura::PropertyConverter* MusClient::GetPropertyConverter() {
  return property_converter_.get();
}

aura::Window* MusClient::GetWindowAtScreenPoint(const gfx::Point& point) {
  for (aura::Window* root : window_tree_client_->GetRoots()) {
    aura::WindowTreeHost* window_tree_host = root->GetHost();
    if (!window_tree_host)
      continue;
    // TODO: this likely gets z-order wrong. http://crbug.com/663606.
    gfx::Point relative_point(point);
    window_tree_host->ConvertScreenInPixelsToDIP(&relative_point);
    if (gfx::Rect(root->bounds().size()).Contains(relative_point))
      return root->GetEventHandlerForPoint(relative_point);
  }
  return nullptr;
}

}  // namespace views
