// Copyright 2018 The Cobalt Authors. 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.

#include "cobalt/dom/generic_event_handler_reference.h"

#include "base/debug/trace_event.h"
#include "cobalt/dom/event.h"
#include "cobalt/dom/event_target.h"
#include "cobalt/dom/script_event_log.h"

namespace cobalt {
namespace dom {

GenericEventHandlerReference::GenericEventHandlerReference(
    script::Wrappable* wrappable,
    const EventListenerScriptValue& script_value) {
  if (!script_value.IsNull()) {
    event_listener_reference_.reset(
        new EventListenerScriptValue::Reference(wrappable, script_value));
  }
}

GenericEventHandlerReference::GenericEventHandlerReference(
    script::Wrappable* wrappable,
    const OnErrorEventListenerScriptValue& script_value) {
  if (!script_value.IsNull()) {
    on_error_event_listener_reference_.reset(
        new OnErrorEventListenerScriptValue::Reference(wrappable,
                                                       script_value));
  }
}

GenericEventHandlerReference::GenericEventHandlerReference(
    script::Wrappable* wrappable, const GenericEventHandlerReference& other) {
  if (other.event_listener_reference_) {
    event_listener_reference_.reset(new EventListenerScriptValue::Reference(
        wrappable, other.event_listener_reference_->referenced_value()));
  } else if (other.on_error_event_listener_reference_) {
    on_error_event_listener_reference_.reset(
        new OnErrorEventListenerScriptValue::Reference(
            wrappable,
            other.on_error_event_listener_reference_->referenced_value()));
  }
}

void GenericEventHandlerReference::HandleEvent(
    const scoped_refptr<Event>& event, bool is_attribute,
    bool unpack_error_event) {
  TRACE_EVENT1("cobalt::dom", "GenericEventHandlerReference::HandleEvent",
               "Event Name", TRACE_STR_COPY(event->type().c_str()));
  script_event_log.Get().PushEvent(event);

  bool had_exception;
  base::optional<bool> result;

  // Forward the HandleEvent() call to the appropriate internal object.
  if (event_listener_reference_) {
    // Non-onerror event handlers cannot have their parameters unpacked.
    result = event_listener_reference_->value().HandleEvent(
        event->current_target(), event, &had_exception);
  } else if (on_error_event_listener_reference_) {
    result = on_error_event_listener_reference_->value().HandleEvent(
        event->current_target(), event, &had_exception, unpack_error_event);
  } else {
    NOTREACHED();
    had_exception = true;
  }

  script_event_log.Get().PopEvent();

  if (had_exception) {
    return;
  }
  // EventHandlers (EventListeners set as attributes) may return false rather
  // than call event.preventDefault() in the handler function.
  if (is_attribute && result && !result.value()) {
    event->PreventDefault();
  }
}

bool GenericEventHandlerReference::EqualTo(
    const EventListenerScriptValue& other) {
  return (IsNull() && other.IsNull()) ||
         (event_listener_reference_ &&
          event_listener_reference_->referenced_value().EqualTo(other));
}

bool GenericEventHandlerReference::EqualTo(
    const GenericEventHandlerReference& other) {
  if (IsNull() && other.IsNull()) {
    return true;
  }

  if (event_listener_reference_ && other.event_listener_reference_) {
    return event_listener_reference_->referenced_value().EqualTo(
        other.event_listener_reference_->referenced_value());
  }
  if (on_error_event_listener_reference_ &&
      other.on_error_event_listener_reference_) {
    return on_error_event_listener_reference_->referenced_value().EqualTo(
        other.on_error_event_listener_reference_->referenced_value());
  }
  return false;
}

bool GenericEventHandlerReference::IsNull() const {
  return (!event_listener_reference_ ||
          event_listener_reference_->referenced_value().IsNull()) &&
         (!on_error_event_listener_reference_ ||
          on_error_event_listener_reference_->referenced_value().IsNull());
}

}  // namespace dom
}  // namespace cobalt
