// Copyright (c) 2012 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/events/event_dispatcher.h"

#include <algorithm>

#include "ui/events/event_target.h"
#include "ui/events/event_targeter.h"

namespace ui {

namespace {

class ScopedDispatchHelper : public Event::DispatcherApi {
 public:
  explicit ScopedDispatchHelper(Event* event)
      : Event::DispatcherApi(event) {
    set_result(ui::ER_UNHANDLED);
  }

  virtual ~ScopedDispatchHelper() {
    set_phase(EP_POSTDISPATCH);
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(ScopedDispatchHelper);
};

}  // namespace

EventDispatcherDelegate::EventDispatcherDelegate()
    : dispatcher_(NULL) {
}

EventDispatcherDelegate::~EventDispatcherDelegate() {
  if (dispatcher_)
    dispatcher_->OnDispatcherDelegateDestroyed();
}

Event* EventDispatcherDelegate::current_event() {
  return dispatcher_ ? dispatcher_->current_event() : NULL;
}

EventDispatchDetails EventDispatcherDelegate::DispatchEvent(EventTarget* target,
                                                            Event* event) {
  CHECK(target);
  Event::DispatcherApi dispatch_helper(event);
  dispatch_helper.set_phase(EP_PREDISPATCH);
  dispatch_helper.set_result(ER_UNHANDLED);

  EventDispatchDetails details = PreDispatchEvent(target, event);
  if (!event->handled() && !details.dispatcher_destroyed)
    details = DispatchEventToTarget(target, event);
  if (!details.dispatcher_destroyed)
    details = PostDispatchEvent(target, *event);

  return details;
}

EventDispatchDetails EventDispatcherDelegate::PreDispatchEvent(
    EventTarget* target, Event* event) {
  return EventDispatchDetails();
}

EventDispatchDetails EventDispatcherDelegate::PostDispatchEvent(
    EventTarget* target, const Event& event) {
  return EventDispatchDetails();
}

EventDispatchDetails EventDispatcherDelegate::DispatchEventToTarget(
    EventTarget* target,
    Event* event) {
  EventDispatcher* old_dispatcher = dispatcher_;
  EventDispatcher dispatcher(this);
  dispatcher_ = &dispatcher;
  dispatcher.ProcessEvent(target, event);
  if (!dispatcher.delegate_destroyed())
    dispatcher_ = old_dispatcher;
  else if (old_dispatcher)
    old_dispatcher->OnDispatcherDelegateDestroyed();

  return dispatcher.details();
}

////////////////////////////////////////////////////////////////////////////////
// EventDispatcher:

EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate)
    : delegate_(delegate),
      current_event_(NULL) {
}

EventDispatcher::~EventDispatcher() {
}

void EventDispatcher::OnHandlerDestroyed(EventHandler* handler) {
  handler_list_.erase(std::find(handler_list_.begin(),
                                handler_list_.end(),
                                handler));
}

void EventDispatcher::ProcessEvent(EventTarget* target, Event* event) {
  if (!target || !target->CanAcceptEvent(*event))
    return;

  ScopedDispatchHelper dispatch_helper(event);
  dispatch_helper.set_target(target);

  handler_list_.clear();
  target->GetPreTargetHandlers(&handler_list_);

  dispatch_helper.set_phase(EP_PRETARGET);
  DispatchEventToEventHandlers(&handler_list_, event);
  if (event->handled())
    return;

  // If the event hasn't been consumed, trigger the default handler. Note that
  // even if the event has already been handled (i.e. return result has
  // ER_HANDLED set), that means that the event should still be processed at
  // this layer, however it should not be processed in the next layer of
  // abstraction.
  if (delegate_ && delegate_->CanDispatchToTarget(target)) {
    dispatch_helper.set_phase(EP_TARGET);
    DispatchEvent(target, event);
    if (event->handled())
      return;
  }

  if (!delegate_)
    return;

  if (!delegate_->CanDispatchToTarget(target)) {
    details_.target_destroyed = true;
    return;
  }

  handler_list_.clear();
  target->GetPostTargetHandlers(&handler_list_);
  dispatch_helper.set_phase(EP_POSTTARGET);
  DispatchEventToEventHandlers(&handler_list_, event);
}

void EventDispatcher::OnDispatcherDelegateDestroyed() {
  details_.dispatcher_destroyed = true;
  delegate_ = NULL;
}

////////////////////////////////////////////////////////////////////////////////
// EventDispatcher, private:

void EventDispatcher::DispatchEventToEventHandlers(EventHandlerList* list,
                                                   Event* event) {
  for (EventHandlerList::const_iterator it = list->begin(),
           end = list->end(); it != end; ++it) {
    (*it)->dispatchers_.push(this);
  }

  while (!list->empty()) {
    EventHandler* handler = (*list->begin());
    if (delegate_ && !event->stopped_propagation())
      DispatchEvent(handler, event);

    if (!list->empty() && *list->begin() == handler) {
      // The handler has not been destroyed (because if it were, then it would
      // have been removed from the list).
      CHECK(handler->dispatchers_.top() == this);
      handler->dispatchers_.pop();
      list->erase(list->begin());
    }
  }
}

void EventDispatcher::DispatchEvent(EventHandler* handler, Event* event) {
  // If the target has been invalidated or deleted, don't dispatch the event.
  if (!delegate_->CanDispatchToTarget(event->target())) {
    details_.target_destroyed = true;
    if (event->cancelable())
      event->StopPropagation();
    return;
  }

  base::AutoReset<Event*> event_reset(&current_event_, event);
  handler->OnEvent(event);
  if (!delegate_ && event->cancelable())
    event->StopPropagation();
}

}  // namespace ui
