// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/globals.h"
#if defined(HOST_OS_FUCHSIA) && defined(SUPPORT_TIMELINE) &&                   \
    !defined(FUCHSIA_SDK)

#include <trace-engine/context.h>
#include <trace-engine/instrumentation.h>
#include <zircon/syscalls.h>

#include "platform/utils.h"
#include "vm/object.h"
#include "vm/timeline.h"

namespace dart {

void TimelineEventFuchsiaRecorder::OnEvent(TimelineEvent* event) {
  if (event == NULL) {
    return;
  }
  TimelineStream* stream = event->stream_;
  trace_string_ref_t category;
  trace_context_t* context = trace_acquire_context_for_category_cached(
      stream->fuchsia_name(), stream->trace_site(), &category);
  if (context == NULL) {
    return;
  }

  trace_string_ref_t name;
  if (event->owns_label()) {
    // If the event owns the name, then the name will be deallocated, so
    // instruct the system trace to make a copy.
    name = trace_context_make_registered_string_copy(
        context, event->label(), strlen(event->label()));
  } else {
    // If the event doesn't own the name, then it is a string literal, and
    // the system trace can use the pointer and not a copy.
    name = trace_context_make_registered_string_literal(
        context, event->label());
  }

  trace_thread_ref_t thread;
  trace_context_register_current_thread(context, &thread);

  trace_arg_t args[TRACE_MAX_ARGS];
  const intptr_t num_args = Utils::Minimum(
      event->arguments_length(), static_cast<intptr_t>(TRACE_MAX_ARGS));

  for (intptr_t i = 0; i < num_args; i++) {
    const char* name = event->arguments()[i].name;
    const char* value = event->arguments()[i].value;
    trace_string_ref_t arg_name =
        trace_context_make_registered_string_literal(context, name);
    trace_string_ref_t arg_value =
        trace_make_inline_string_ref(value, strlen(value));
    args[i] = trace_make_arg(arg_name, trace_make_string_arg_value(arg_value));
  }

  const uint64_t time_scale = zx_ticks_per_second() / kMicrosecondsPerSecond;
  const uint64_t start_time = event->LowTime() * time_scale;
  const uint64_t end_time = event->HighTime() * time_scale;

  // TODO(zra): The functions below emit Dart's timeline events all as category
  // "dart". Instead, we could have finer-grained categories that make use of
  // the name of the timeline stream, e.g. "VM", "GC", etc.
  switch (event->event_type()) {
    case TimelineEvent::kBegin:
      trace_context_write_duration_begin_event_record(
          context, start_time, &thread, &category, &name, args, num_args);
      break;
    case TimelineEvent::kEnd:
      trace_context_write_duration_end_event_record(
          context, start_time, &thread, &category, &name, args, num_args);
      break;
    case TimelineEvent::kInstant:
      trace_context_write_instant_event_record(
          context, start_time, &thread, &category, &name, TRACE_SCOPE_THREAD,
          args, num_args);
      break;
    case TimelineEvent::kAsyncBegin:
      trace_context_write_async_begin_event_record(
          context, start_time, &thread, &category, &name, event->AsyncId(),
          args, num_args);
      break;
    case TimelineEvent::kAsyncEnd:
      trace_context_write_async_end_event_record(
          context, end_time, &thread, &category, &name, event->AsyncId(), args,
          num_args);
      break;
    case TimelineEvent::kAsyncInstant:
      trace_context_write_async_instant_event_record(
          context, start_time, &thread, &category, &name, event->AsyncId(),
          args, num_args);
      break;
    case TimelineEvent::kDuration:
      trace_context_write_duration_event_record(context, start_time, end_time,
                                                &thread, &category, &name, args,
                                                num_args);
      break;
    case TimelineEvent::kFlowBegin:
      trace_context_write_flow_begin_event_record(
          context, start_time, &thread, &category, &name, event->AsyncId(),
          args, num_args);
      break;
    case TimelineEvent::kFlowStep:
      trace_context_write_flow_step_event_record(
          context, start_time, &thread, &category, &name, event->AsyncId(),
          args, num_args);
      break;
    case TimelineEvent::kFlowEnd:
      trace_context_write_flow_end_event_record(
          context, start_time, &thread, &category, &name, event->AsyncId(),
          args, num_args);
      break;
    default:
      // TODO(zra): Figure out what to do with kCounter and kMetadata.
      break;
  }
  trace_release_context(context);
}

}  // namespace dart

#endif  // defined(HOST_OS_FUCHSIA) && !defined(PRODUCT)
