/*
 * Copyright 2016 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.
 */

#include "cobalt/dom/event_listener.h"

#include "base/debug/trace_event.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "cobalt/base/user_log.h"
#include "cobalt/dom/event_target.h"

namespace cobalt {
namespace dom {
namespace {

// This class records the nested events and manages the user log information.
class ScriptEventLog {
 public:
  ScriptEventLog() : current_stack_depth_(0) {
    base::UserLog::Register(base::UserLog::kEventStackLevelCountIndex,
                            "EventLevelCnt", &current_stack_depth_,
                            sizeof(current_stack_depth_));

    memset(event_log_stack_, 0, sizeof(event_log_stack_));
    const int kLogNameBufferSize = 16;
    char log_name_buffer[kLogNameBufferSize];
    for (int i = 0; i < base::UserLog::kEventStackMaxDepth; i++) {
      snprintf(log_name_buffer, kLogNameBufferSize, "EventLevel%d", i);
      base::UserLog::Register(static_cast<base::UserLog::Index>(
                                  base::UserLog::kEventStackMinLevelIndex + i),
                              log_name_buffer, event_log_stack_[i],
                              kLogEntryMaxLength);
    }
  }

  ~ScriptEventLog() {
    base::UserLog::Deregister(base::UserLog::kEventStackLevelCountIndex);
    for (int i = 0; i < base::UserLog::kEventStackMaxDepth; i++) {
      base::UserLog::Deregister(static_cast<base::UserLog::Index>(
          base::UserLog::kEventStackMinLevelIndex + i));
    }
  }

  void PushEvent(Event* event) {
    if (current_stack_depth_ < base::UserLog::kEventStackMaxDepth) {
      snprintf(event_log_stack_[current_stack_depth_], kLogEntryMaxLength,
               "%s@%s", event->type().c_str(),
               event->current_target()->GetDebugName().c_str());
    } else if (current_stack_depth_ == base::UserLog::kEventStackMaxDepth) {
      DLOG(WARNING) << "Reached maximum depth of " << kLogEntryMaxLength
                    << ". Subsequent events will not be logged.";
    }
    current_stack_depth_++;
  }

  void PopEvent() {
    DCHECK(current_stack_depth_);
    current_stack_depth_--;
    if (current_stack_depth_ < base::UserLog::kEventStackMaxDepth) {
      memset(event_log_stack_[current_stack_depth_], 0, kLogEntryMaxLength);
    }
  }

 private:
  static const size_t kLogEntryMaxLength = 64;
  int current_stack_depth_;
  char event_log_stack_[base::UserLog::kEventStackMaxDepth][kLogEntryMaxLength];

  DISALLOW_COPY_AND_ASSIGN(ScriptEventLog);
};

base::LazyInstance<ScriptEventLog> script_event_log = LAZY_INSTANCE_INITIALIZER;

}  // namespace

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

  bool had_exception;
  base::optional<bool> result =
      HandleEvent(event->current_target(), event, &had_exception);

  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 (listener_type == kAttribute && result && !result.value()) {
    event->PreventDefault();
  }
}

}  // namespace dom
}  // namespace cobalt
