// Copyright 2014 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 "base/bind.h"
#include "base/macros.h"
#include "mojo/application/application_runner_chromium.h"
#include "mojo/converters/geometry/geometry_type_converters.h"
#include "mojo/converters/input_events/input_events_type_converters.h"
#include "mojo/examples/keyboard/keyboard.mojom.h"
#include "mojo/examples/window_manager/debug_panel.h"
#include "mojo/examples/window_manager/window_manager.mojom.h"
#include "mojo/public/c/system/main.h"
#include "mojo/public/cpp/application/application_connection.h"
#include "mojo/public/cpp/application/application_delegate.h"
#include "mojo/public/cpp/application/application_impl.h"
#include "mojo/public/cpp/application/interface_factory_impl.h"
#include "mojo/public/cpp/application/service_provider_impl.h"
#include "mojo/services/public/cpp/view_manager/view.h"
#include "mojo/services/public/cpp/view_manager/view_manager.h"
#include "mojo/services/public/cpp/view_manager/view_manager_delegate.h"
#include "mojo/services/public/cpp/view_manager/view_observer.h"
#include "mojo/services/public/interfaces/input_events/input_events.mojom.h"
#include "mojo/services/public/interfaces/navigation/navigation.mojom.h"
#include "mojo/services/window_manager/window_manager_app.h"
#include "mojo/services/window_manager/window_manager_delegate.h"
#include "mojo/views/views_init.h"
#include "ui/aura/window.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/wm/core/focus_rules.h"

#if defined CreateWindow
#undef CreateWindow
#endif

namespace mojo {
namespace examples {

class WindowManager;

namespace {

const int kBorderInset = 25;
const int kControlPanelWidth = 200;
const int kTextfieldHeight = 25;

class WMFocusRules : public wm::FocusRules {
 public:
  WMFocusRules(mojo::WindowManagerApp* window_manager_app,
               mojo::View* window_container)
      : window_container_(window_container),
        window_manager_app_(window_manager_app) {}
  virtual ~WMFocusRules() {}

 private:
  // Overridden from wm::FocusRules:
  virtual bool IsToplevelWindow(aura::Window* window) const override {
    return mojo::WindowManagerApp::GetViewForWindow(window)->parent() ==
        window_container_;
  }
  virtual bool CanActivateWindow(aura::Window* window) const override {
    return mojo::WindowManagerApp::GetViewForWindow(window)->parent() ==
        window_container_;
  }
  virtual bool CanFocusWindow(aura::Window* window) const override {
    return true;
  }
  virtual aura::Window* GetToplevelWindow(aura::Window* window) const override {
    mojo::View* view = mojo::WindowManagerApp::GetViewForWindow(window);
    while (view->parent() != window_container_) {
      view = view->parent();
      // Unparented hierarchy, there is no "top level" window.
      if (!view)
        return NULL;
    }

    return window_manager_app_->GetWindowForViewId(view->id());
  }
  virtual aura::Window* GetActivatableWindow(
      aura::Window* window) const override {
    return GetToplevelWindow(window);
  }
  virtual aura::Window* GetFocusableWindow(
      aura::Window* window) const override {
    return window;
  }
  virtual aura::Window* GetNextActivatableWindow(
      aura::Window* ignore) const override {
    aura::Window* activatable = GetActivatableWindow(ignore);
    const aura::Window::Windows& children = activatable->parent()->children();
    for (aura::Window::Windows::const_reverse_iterator it = children.rbegin();
         it != children.rend(); ++it) {
      if (*it != ignore)
        return *it;
    }
    return NULL;
  }

  mojo::View* window_container_;
  mojo::WindowManagerApp* window_manager_app_;

  DISALLOW_COPY_AND_ASSIGN(WMFocusRules);
};

}  // namespace

class WindowManagerConnection : public InterfaceImpl<IWindowManager> {
 public:
  explicit WindowManagerConnection(WindowManager* window_manager)
      : window_manager_(window_manager) {}
  virtual ~WindowManagerConnection() {}

 private:
  // Overridden from IWindowManager:
  virtual void CloseWindow(Id view_id) override;
  virtual void ShowKeyboard(Id view_id, RectPtr bounds) override;
  virtual void HideKeyboard(Id view_id) override;

  WindowManager* window_manager_;

  DISALLOW_COPY_AND_ASSIGN(WindowManagerConnection);
};

class NavigatorHostImpl : public InterfaceImpl<NavigatorHost> {
 public:
  explicit NavigatorHostImpl(WindowManager* window_manager, Id view_id)
      : window_manager_(window_manager), view_id_(view_id) {}
  virtual ~NavigatorHostImpl() {
  }

 private:
  virtual void DidNavigateLocally(const mojo::String& url) override;
  virtual void RequestNavigate(Target target, URLRequestPtr request) override;

  WindowManager* window_manager_;
  Id view_id_;

  DISALLOW_COPY_AND_ASSIGN(NavigatorHostImpl);
};

class KeyboardManager : public KeyboardClient,
                        public ViewObserver {
 public:
  KeyboardManager() : view_manager_(NULL), view_(NULL) {
  }
  virtual ~KeyboardManager() {
    if (view_)
      view_->parent()->RemoveObserver(this);
  }

  View* view() { return view_; }

  void Init(ApplicationImpl* application,
            ViewManager* view_manager,
            View* parent,
            const gfx::Rect& bounds) {
    view_manager_ = view_manager;
    view_ = View::Create(view_manager);
    view_->SetBounds(bounds);
    parent->AddChild(view_);
    view_->Embed("mojo:mojo_keyboard");
    application->ConnectToService("mojo:mojo_keyboard", &keyboard_service_);
    keyboard_service_.set_client(this);
    parent->AddObserver(this);
  }

  void Show(Id view_id, const gfx::Rect& bounds) {
    keyboard_service_->SetTarget(view_id);
    view_->SetVisible(true);
  }

  void Hide(Id view_id) {
    keyboard_service_->SetTarget(0);
    view_->SetVisible(false);
  }

 private:
  // KeyboardClient:
  virtual void OnKeyboardEvent(Id view_id,
                               int32_t code,
                               int32_t flags) override {
    // TODO(sky): figure this out. Code use to dispatch events, but that's a
    // hack. Instead strings should be passed through, or maybe a richer text
    // input interface.
  }

  // Overridden from ViewObserver:
  virtual void OnViewBoundsChanged(View* parent,
                                   const gfx::Rect& old_bounds,
                                   const gfx::Rect& new_bounds) override {
    gfx::Rect keyboard_bounds(view_->bounds());
    keyboard_bounds.set_y(new_bounds.bottom() - keyboard_bounds.height());
    keyboard_bounds.set_width(keyboard_bounds.width() +
                              new_bounds.width() - old_bounds.width());
    view_->SetBounds(keyboard_bounds);
  }
  virtual void OnViewDestroyed(View* parent) override {
    DCHECK_EQ(parent, view_->parent());
    parent->RemoveObserver(this);
    view_ = NULL;
  }

  KeyboardServicePtr keyboard_service_;
  ViewManager* view_manager_;

  // View the keyboard is attached to.
  View* view_;

  DISALLOW_COPY_AND_ASSIGN(KeyboardManager);
};

class RootLayoutManager : public ViewObserver {
 public:
  RootLayoutManager(ViewManager* view_manager,
                    View* root,
                    Id content_view_id,
                    Id launcher_ui_view_id,
                    Id control_panel_view_id)
      : root_(root),
        view_manager_(view_manager),
        content_view_id_(content_view_id),
        launcher_ui_view_id_(launcher_ui_view_id),
        control_panel_view_id_(control_panel_view_id) {}
  virtual ~RootLayoutManager() {
    if (root_)
      root_->RemoveObserver(this);
  }

 private:
  // Overridden from ViewObserver:
  virtual void OnViewBoundsChanged(View* view,
                                   const gfx::Rect& old_bounds,
                                   const gfx::Rect& new_bounds) override {
    DCHECK_EQ(view, root_);

    View* content_view = view_manager_->GetViewById(content_view_id_);
    content_view->SetBounds(new_bounds);

    int delta_width = new_bounds.width() - old_bounds.width();
    int delta_height = new_bounds.height() - old_bounds.height();

    View* launcher_ui_view =
        view_manager_->GetViewById(launcher_ui_view_id_);
    gfx::Rect launcher_ui_bounds(launcher_ui_view->bounds());
    launcher_ui_bounds.set_width(launcher_ui_bounds.width() + delta_width);
    launcher_ui_view->SetBounds(launcher_ui_bounds);

    View* control_panel_view =
        view_manager_->GetViewById(control_panel_view_id_);
    gfx::Rect control_panel_bounds(control_panel_view->bounds());
    control_panel_bounds.set_x(control_panel_bounds.x() + delta_width);
    control_panel_view->SetBounds(control_panel_bounds);

    const View::Children& content_views = content_view->children();
    View::Children::const_iterator iter = content_views.begin();
    for(; iter != content_views.end(); ++iter) {
      View* view = *iter;
      if (view->id() == control_panel_view->id() ||
          view->id() == launcher_ui_view->id())
        continue;
      gfx::Rect view_bounds(view->bounds());
      view_bounds.set_width(view_bounds.width() + delta_width);
      view_bounds.set_height(view_bounds.height() + delta_height);
      view->SetBounds(view_bounds);
    }
  }
  virtual void OnViewDestroyed(View* view) override {
    DCHECK_EQ(view, root_);
    root_->RemoveObserver(this);
    root_ = NULL;
  }

  View* root_;
  ViewManager* view_manager_;
  const Id content_view_id_;
  const Id launcher_ui_view_id_;
  const Id control_panel_view_id_;

  DISALLOW_COPY_AND_ASSIGN(RootLayoutManager);
};

class Window : public InterfaceFactory<NavigatorHost> {
 public:
  Window(WindowManager* window_manager, View* view)
      : window_manager_(window_manager), view_(view) {}

  virtual ~Window() {}

  View* view() const { return view_; }

  void Embed(const std::string& url) {
    scoped_ptr<ServiceProviderImpl> service_provider_impl(
        new ServiceProviderImpl());
    service_provider_impl->AddService<NavigatorHost>(this);
    view_->Embed(url, service_provider_impl.Pass());
  }

 private:
  // InterfaceFactory<NavigatorHost>
  virtual void Create(ApplicationConnection* connection,
                      InterfaceRequest<NavigatorHost> request) override {
    BindToRequest(new NavigatorHostImpl(window_manager_, view_->id()),
                  &request);
  }

  WindowManager* window_manager_;
  View* view_;
};

class WindowManager
    : public ApplicationDelegate,
      public DebugPanel::Delegate,
      public ViewManagerDelegate,
      public WindowManagerDelegate,
      public ui::EventHandler {
 public:
  WindowManager()
      : shell_(nullptr),
        window_manager_factory_(this),
        launcher_ui_(NULL),
        view_manager_(NULL),
        window_manager_app_(new WindowManagerApp(this, this)),
        app_(NULL) {}

  virtual ~WindowManager() {
    // host() may be destroyed by the time we get here.
    // TODO: figure out a way to always cleanly remove handler.
    if (window_manager_app_->host())
      window_manager_app_->host()->window()->RemovePreTargetHandler(this);
  }

  void CloseWindow(Id view_id) {
    WindowVector::iterator iter = GetWindowByViewId(view_id);
    DCHECK(iter != windows_.end());
    Window* window = *iter;
    windows_.erase(iter);
    window->view()->Destroy();
  }

  void ShowKeyboard(Id view_id, const gfx::Rect& bounds) {
    // TODO: this needs to validate |view_id|. That is, it shouldn't assume
    // |view_id| is valid and it also needs to make sure the client that sent
    // this really owns |view_id|.
    // TODO: honor |bounds|.
    if (!keyboard_manager_) {
      keyboard_manager_.reset(new KeyboardManager);
      View* parent = view_manager_->GetRoots().back();
      int ideal_height = 200;
      // TODO(sky): 10 is a bit of a hack here. There is a bug that causes
      // white strips to appear when 0 is used. Figure this out!
      const gfx::Rect keyboard_bounds(
          10, parent->bounds().height() - ideal_height,
          parent->bounds().width() - 20, ideal_height);
      keyboard_manager_->Init(app_, view_manager_, parent, keyboard_bounds);
    }
    keyboard_manager_->Show(view_id, bounds);
  }

  void HideKeyboard(Id view_id) {
    // See comment in ShowKeyboard() about validating args.
    if (keyboard_manager_)
      keyboard_manager_->Hide(view_id);
  }

  void DidNavigateLocally(uint32 source_view_id, const mojo::String& url) {
    LOG(ERROR) << "DidNavigateLocally: source_view_id: " << source_view_id
               << " url: " << url.To<std::string>();
  }

  // Overridden from DebugPanel::Delegate:
  virtual void CloseTopWindow() override {
    if (!windows_.empty())
      CloseWindow(windows_.back()->view()->id());
  }

  virtual void RequestNavigate(uint32 source_view_id,
                               Target target,
                               URLRequestPtr request) override {
    OnLaunch(source_view_id, target, request->url);
  }

 private:
  typedef std::vector<Window*> WindowVector;

  // Overridden from ApplicationDelegate:
  virtual void Initialize(ApplicationImpl* app) override {
    shell_ = app->shell();
    app_ = app;
    views_init_.reset(new ViewsInit);
    window_manager_app_->Initialize(app);
  }

  virtual bool ConfigureIncomingConnection(
      ApplicationConnection* connection) override {
    connection->AddService(&window_manager_factory_);
    window_manager_app_->ConfigureIncomingConnection(connection);
    return true;
  }

  // Overridden from ViewManagerDelegate:
  virtual void OnEmbed(ViewManager* view_manager,
                       View* root,
                       ServiceProviderImpl* exported_services,
                       scoped_ptr<ServiceProvider> imported_services) override {
    DCHECK(!view_manager_);
    view_manager_ = view_manager;

    View* view = View::Create(view_manager_);
    root->AddChild(view);
    view->SetBounds(gfx::Rect(root->bounds().size()));
    content_view_id_ = view->id();

    Id launcher_ui_id = CreateLauncherUI();
    Id control_panel_id = CreateControlPanel(view);

    root_layout_manager_.reset(
        new RootLayoutManager(view_manager, root,
                              content_view_id_,
                              launcher_ui_id,
                              control_panel_id));
    root->AddObserver(root_layout_manager_.get());

    window_manager_app_->host()->window()->AddPreTargetHandler(this);

    window_manager_app_->InitFocus(new WMFocusRules(window_manager_app_.get(),
                                                    view));
  }
  virtual void OnViewManagerDisconnected(ViewManager* view_manager) override {
    DCHECK_EQ(view_manager_, view_manager);
    view_manager_ = NULL;
    base::MessageLoop::current()->Quit();
  }

  // Overridden from WindowManagerDelegate:
  virtual void Embed(
      const String& url,
      InterfaceRequest<ServiceProvider> service_provider) override {
    const Id kInvalidSourceViewId = 0;
    OnLaunch(kInvalidSourceViewId, TARGET_DEFAULT, url);
  }

  // Overridden from ui::EventHandler:
  virtual void OnEvent(ui::Event* event) override {
    View* view = WindowManagerApp::GetViewForWindow(
        static_cast<aura::Window*>(event->target()));
    if (event->type() == ui::ET_MOUSE_PRESSED &&
        !IsDescendantOfKeyboard(view)) {
      view->SetFocus();
    }
  }

  void OnLaunch(uint32 source_view_id,
                Target requested_target,
                const mojo::String& url) {
    Target target = debug_panel_->navigation_target();
    if (target == TARGET_DEFAULT) {
      if (requested_target != TARGET_DEFAULT) {
        target = requested_target;
      } else {
        // TODO(aa): Should be TARGET_NEW_NODE if source origin and dest origin
        // are different?
        target = TARGET_SOURCE_NODE;
      }
    }

    Window* dest_view = NULL;
    if (target == TARGET_SOURCE_NODE) {
      WindowVector::iterator source_view = GetWindowByViewId(source_view_id);
      bool app_initiated = source_view != windows_.end();
      if (app_initiated)
        dest_view = *source_view;
      else if (!windows_.empty())
        dest_view = windows_.back();
    }

    if (!dest_view) {
      dest_view = CreateWindow();
      windows_.push_back(dest_view);
    }

    dest_view->Embed(url);
  }

  // TODO(beng): proper layout manager!!
  Id CreateLauncherUI() {
    View* view = view_manager_->GetViewById(content_view_id_);
    gfx::Rect bounds = view->bounds();
    bounds.Inset(kBorderInset, kBorderInset);
    bounds.set_height(kTextfieldHeight);
    launcher_ui_ = CreateWindow(bounds);
    launcher_ui_->Embed("mojo:mojo_browser");
    return launcher_ui_->view()->id();
  }

  Window* CreateWindow() {
    View* view = view_manager_->GetViewById(content_view_id_);
    gfx::Rect bounds(kBorderInset,
                     2 * kBorderInset + kTextfieldHeight,
                     view->bounds().width() - 3 * kBorderInset -
                         kControlPanelWidth,
                     view->bounds().height() -
                         (3 * kBorderInset + kTextfieldHeight));
    if (!windows_.empty()) {
      gfx::Point position = windows_.back()->view()->bounds().origin();
      position.Offset(35, 35);
      bounds.set_origin(position);
    }
    return CreateWindow(bounds);
  }

  Window* CreateWindow(const gfx::Rect& bounds) {
    View* content = view_manager_->GetViewById(content_view_id_);
    View* view = View::Create(view_manager_);
    content->AddChild(view);
    view->SetBounds(bounds);
    view->SetFocus();
    return new Window(this, view);
  }

  bool IsDescendantOfKeyboard(View* target) {
    return keyboard_manager_.get() &&
        keyboard_manager_->view()->Contains(target);
  }

  Id CreateControlPanel(View* root) {
    View* view = View::Create(view_manager_);
    root->AddChild(view);

    gfx::Rect bounds(root->bounds().width() - kControlPanelWidth -
                         kBorderInset,
                     kBorderInset * 2 + kTextfieldHeight,
                     kControlPanelWidth,
                     root->bounds().height() - kBorderInset * 3 -
                         kTextfieldHeight);
    view->SetBounds(bounds);

    debug_panel_ = new DebugPanel(this, shell_, view);
    return view->id();
  }

  WindowVector::iterator GetWindowByViewId(Id view_id) {
    for (std::vector<Window*>::iterator iter = windows_.begin();
         iter != windows_.end();
         ++iter) {
      if ((*iter)->view()->id() == view_id) {
        return iter;
      }
    }
    return windows_.end();
  }

  Shell* shell_;

  InterfaceFactoryImplWithContext<WindowManagerConnection, WindowManager>
      window_manager_factory_;

  scoped_ptr<ViewsInit> views_init_;
  DebugPanel* debug_panel_;
  Window* launcher_ui_;
  WindowVector windows_;
  ViewManager* view_manager_;
  scoped_ptr<RootLayoutManager> root_layout_manager_;

  scoped_ptr<WindowManagerApp> window_manager_app_;

  // Id of the view most content is added to. The keyboard is NOT added here.
  Id content_view_id_;

  scoped_ptr<KeyboardManager> keyboard_manager_;
  ApplicationImpl* app_;

  DISALLOW_COPY_AND_ASSIGN(WindowManager);
};

void WindowManagerConnection::CloseWindow(Id view_id) {
  window_manager_->CloseWindow(view_id);
}

void WindowManagerConnection::ShowKeyboard(Id view_id, RectPtr bounds) {
  window_manager_->ShowKeyboard(view_id, bounds.To<gfx::Rect>());
}

void WindowManagerConnection::HideKeyboard(Id view_id) {
  window_manager_->HideKeyboard(view_id);
}

void NavigatorHostImpl::DidNavigateLocally(const mojo::String& url) {
  window_manager_->DidNavigateLocally(view_id_, url);
}

void NavigatorHostImpl::RequestNavigate(Target target, URLRequestPtr request) {
  window_manager_->RequestNavigate(view_id_, target, request.Pass());
}

}  // namespace examples
}  // namespace mojo

MojoResult MojoMain(MojoHandle shell_handle) {
  mojo::ApplicationRunnerChromium runner(new mojo::examples::WindowManager);
  return runner.Run(shell_handle);
}
