// Copyright (c) 2013 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 "ash/display/mirror_window_controller.h"

#if defined(USE_X11)
#include <X11/Xlib.h>

// Xlib.h defines RootWindow.
#undef RootWindow
#endif

#include "ash/display/cursor_window_controller.h"
#include "ash/display/display_controller.h"
#include "ash/display/display_info.h"
#include "ash/display/display_manager.h"
#include "ash/display/root_window_transformers.h"
#include "ash/host/ash_window_tree_host.h"
#include "ash/host/ash_window_tree_host_init_params.h"
#include "ash/host/root_window_transformer.h"
#include "ash/root_window_settings.h"
#include "ash/shell.h"
#include "base/strings/stringprintf.h"
#include "ui/aura/client/capture_client.h"
#include "ui/aura/env.h"
#include "ui/aura/window_delegate.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/layout.h"
#include "ui/compositor/reflector.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/native_widget_types.h"

#if defined(USE_X11)
#include "ui/gfx/x/x11_types.h"
#endif

namespace ash {
namespace {

#if defined(USE_X11)
// Mirror window shouldn't handle input events.
void DisableInput(XID window) {
  long event_mask = ExposureMask | VisibilityChangeMask |
      StructureNotifyMask | PropertyChangeMask;
  XSelectInput(gfx::GetXDisplay(), window, event_mask);
}
#endif

class NoneCaptureClient : public aura::client::CaptureClient {
 public:
  NoneCaptureClient() {}
  virtual ~NoneCaptureClient() {}

 private:
  // Does a capture on the |window|.
  virtual void SetCapture(aura::Window* window) OVERRIDE {}

  // Releases a capture from the |window|.
  virtual void ReleaseCapture(aura::Window* window) OVERRIDE {}

  // Returns the current capture window.
  virtual aura::Window* GetCaptureWindow() OVERRIDE {
    return NULL;
  }
  virtual aura::Window* GetGlobalCaptureWindow() OVERRIDE {
    return NULL;
  }

  DISALLOW_COPY_AND_ASSIGN(NoneCaptureClient);
};

}  // namespace

MirrorWindowController::MirrorWindowController() {}

MirrorWindowController::~MirrorWindowController() {
  // Make sure the root window gets deleted before cursor_window_delegate.
  Close();
}

void MirrorWindowController::UpdateWindow(const DisplayInfo& display_info) {
  static int mirror_host_count = 0;
  if (!ash_host_.get()) {
    AshWindowTreeHostInitParams init_params;
    init_params.initial_bounds = display_info.bounds_in_native();
    ash_host_.reset(AshWindowTreeHost::Create(init_params));
    aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost();
    host->window()->SetName(
        base::StringPrintf("MirrorRootWindow-%d", mirror_host_count++));
    host->compositor()->SetBackgroundColor(SK_ColorBLACK);
    // No need to remove the observer because the DisplayController outlives the
    // host.
    host->AddObserver(Shell::GetInstance()->display_controller());
    host->AddObserver(this);
    // TODO(oshima): TouchHUD is using idkey.
    InitRootWindowSettings(host->window())->display_id = display_info.id();
    host->InitHost();
#if defined(USE_X11)
    DisableInput(host->GetAcceleratedWidget());
#endif

    aura::client::SetCaptureClient(host->window(), new NoneCaptureClient());
    host->Show();

    // TODO(oshima): Start mirroring.
    aura::Window* mirror_window = new aura::Window(NULL);
    mirror_window->Init(aura::WINDOW_LAYER_TEXTURED);
    host->window()->AddChild(mirror_window);
    mirror_window->SetBounds(host->window()->bounds());
    mirror_window->Show();
    reflector_ = aura::Env::GetInstance()->context_factory()->CreateReflector(
        Shell::GetPrimaryRootWindow()->GetHost()->compositor(),
        mirror_window->layer());
  } else {
    aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost();
    GetRootWindowSettings(host->window())->display_id = display_info.id();
    host->SetBounds(display_info.bounds_in_native());
  }

  DisplayManager* display_manager = Shell::GetInstance()->display_manager();
  const DisplayInfo& source_display_info = display_manager->GetDisplayInfo(
      Shell::GetScreen()->GetPrimaryDisplay().id());
  DCHECK(display_manager->IsMirrored());
  scoped_ptr<RootWindowTransformer> transformer(
      CreateRootWindowTransformerForMirroredDisplay(source_display_info,
                                                    display_info));
  ash_host_->SetRootWindowTransformer(transformer.Pass());
}

void MirrorWindowController::UpdateWindow() {
  if (ash_host_.get()) {
    DisplayManager* display_manager = Shell::GetInstance()->display_manager();
    const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo(
        display_manager->mirrored_display_id());
    UpdateWindow(mirror_display_info);
  }
}

void MirrorWindowController::Close() {
  if (ash_host_.get()) {
    aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost();
    aura::Env::GetInstance()->context_factory()->RemoveReflector(reflector_);
    reflector_ = NULL;
    NoneCaptureClient* capture_client = static_cast<NoneCaptureClient*>(
        aura::client::GetCaptureClient(host->window()));
    aura::client::SetCaptureClient(host->window(), NULL);
    delete capture_client;

    host->RemoveObserver(Shell::GetInstance()->display_controller());
    host->RemoveObserver(this);
    ash_host_.reset();
  }
}

void MirrorWindowController::OnHostResized(const aura::WindowTreeHost* host) {
  if (mirror_window_host_size_ == host->GetBounds().size())
    return;
  mirror_window_host_size_ = host->GetBounds().size();
  reflector_->OnMirroringCompositorResized();
  ash_host_->SetRootWindowTransformer(CreateRootWindowTransformer().Pass());
  Shell::GetInstance()->display_controller()->cursor_window_controller()->
      UpdateLocation();
}

aura::Window* MirrorWindowController::GetWindow() {
  return ash_host_.get() ? ash_host_->AsWindowTreeHost()->window() : NULL;
}

scoped_ptr<RootWindowTransformer>
MirrorWindowController::CreateRootWindowTransformer() const {
  DisplayManager* display_manager = Shell::GetInstance()->display_manager();
  const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo(
      display_manager->mirrored_display_id());
  const DisplayInfo& source_display_info = display_manager->GetDisplayInfo(
      Shell::GetScreen()->GetPrimaryDisplay().id());
  DCHECK(display_manager->IsMirrored());
  return scoped_ptr<RootWindowTransformer>(
      CreateRootWindowTransformerForMirroredDisplay(source_display_info,
                                                    mirror_display_info));
}

}  // namespace ash
