// 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>

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;
}

bool EventDispatcherDelegate::DispatchEvent(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.delegate_destroyed();
}

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_ || !delegate_->CanDispatchToTarget(target))
    return;

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

void EventDispatcher::OnDispatcherDelegateDestroyed() {
  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())) {
    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
