/*
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef COBALT_DOM_EVENT_H_
#define COBALT_DOM_EVENT_H_

#include <string>

#include "base/memory/weak_ptr.h"
#include "cobalt/base/token.h"
#include "cobalt/script/wrappable.h"

namespace cobalt {
namespace dom {

// The forward declaration is necessary for breaking the bi-directional
// dependency between Event and EventTarget.
class EventTarget;

// The Event interface can be passed from the event target to event listener to
// pass information between them.
//   https://www.w3.org/TR/2014/WD-dom-20140710/#interface-event
//
// TODO: We only support the attributes/methods that are in use.
// We need to investigate the exact subset of them required in Cobalt.
class Event : public script::Wrappable {
 public:
  // Web API: Event
  // EventPhase values as defined by Web API Event.eventPhase.
  //
  enum EventPhase { kNone, kCapturingPhase, kAtTarget, kBubblingPhase };

  // Custom, not in any spec.
  //
  enum Bubbles { kNotBubbles, kBubbles };

  enum Cancelable { kNotCancelable, kCancelable };

  enum UninitializedFlag { Uninitialized };

  // Creates an event with its "initialized flag" unset.
  explicit Event(UninitializedFlag uninitialized_flag);

  // Creates an event that cannot be bubbled and cancelled.
  explicit Event(base::Token type);
  explicit Event(const std::string& type);
  Event(base::Token type, Bubbles bubbles, Cancelable cancelable);
  ~Event() OVERRIDE;

  // Web API: Event
  //
  base::Token type() const { return type_; }
  const scoped_refptr<EventTarget>& target() const;
  const scoped_refptr<EventTarget>& current_target() const;
  EventPhase event_phase() const { return event_phase_; }

  void StopPropagation() { propagation_stopped_ = true; }
  void StopImmediatePropagation() {
    propagation_stopped_ = true;
    immediate_propagation_stopped_ = true;
  }

  bool bubbles() const { return bubbles_; }
  bool cancelable() const { return cancelable_; }
  void PreventDefault() {
    if (cancelable()) {
      default_prevented_ = true;
    }
  }
  bool default_prevented() const { return default_prevented_; }

  uint64 time_stamp() const { return time_stamp_; }

  void InitEvent(const std::string& type, bool bubbles, bool cancelable);

  // Custom, not in any spec.
  //
  bool IsBeingDispatched() const { return event_phase() != kNone; }
  void set_target(const scoped_refptr<EventTarget>& target);
  void set_current_target(const scoped_refptr<EventTarget>& target);
  void set_event_phase(EventPhase event_phase) { event_phase_ = event_phase; }
  // We link whether the event has the "initialized flag" set to whether it has
  // a non-empty type.  Note that the spec doesn't explicitly prevent an Event
  // to have empty string as its type but it is reasonable to make this
  // assumption and Chrome has the same behavior.
  bool initialized_flag() const { return type_ != ""; }

  // The event dispatching process usually looks like:
  //
  // for (each event target) {
  //   for (each event listener in the current target) {
  //     listener->handleEvent(event);
  //     if (event->immediate_propagation_stopped()) break;
  //   }
  //   if (event->propagation_stopped()) break;
  // }
  //
  // When propagation_stopped() returns true, the inside loop will continue but
  // the outside loop will break.
  bool propagation_stopped() const { return propagation_stopped_; }
  // When immediate_propagation_stopped() returns true, the inside loop will
  // break. As StopImmediatePropagation() will also set propagation_stopped_ to
  // true. This implies the outside loop will be break too.
  bool immediate_propagation_stopped() const {
    return immediate_propagation_stopped_;
  }

  DEFINE_WRAPPABLE_TYPE(Event);

 private:
  void InitEventInternal(base::Token type, bool bubbles, bool cancelable);

  base::Token type_;

  scoped_refptr<EventTarget> target_;
  scoped_refptr<EventTarget> current_target_;
  EventPhase event_phase_;

  bool propagation_stopped_;
  bool immediate_propagation_stopped_;

  bool bubbles_;
  bool cancelable_;
  bool default_prevented_;

  uint64 time_stamp_;
};

}  // namespace dom
}  // namespace cobalt

#endif  // COBALT_DOM_EVENT_H_
