/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * 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 "src/trace_processor/importers/json/json_trace_parser.h"

#include <cinttypes>
#include <limits>
#include <optional>
#include <string>

#include "perfetto/base/logging.h"
#include "perfetto/ext/base/string_utils.h"
#include "perfetto/ext/base/string_view.h"
#include "src/trace_processor/importers/common/event_tracker.h"
#include "src/trace_processor/importers/common/flow_tracker.h"
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/importers/common/slice_tracker.h"
#include "src/trace_processor/importers/common/track_tracker.h"
#include "src/trace_processor/importers/json/json_utils.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/types/trace_processor_context.h"

namespace perfetto {
namespace trace_processor {

#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
namespace {

std::optional<uint64_t> MaybeExtractFlowIdentifier(const Json::Value& value,
                                                   bool version2) {
  std::string id_key = (version2 ? "bind_id" : "id");
  if (!value.isMember(id_key))
    return std::nullopt;
  auto id = value[id_key];
  if (id.isNumeric())
    return id.asUInt64();
  if (!id.isString())
    return std::nullopt;
  const char* c_string = id.asCString();
  return base::CStringToUInt64(c_string, 16);
}

}  // namespace
#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)

JsonTraceParser::JsonTraceParser(TraceProcessorContext* context)
    : context_(context), systrace_line_parser_(context) {}

JsonTraceParser::~JsonTraceParser() = default;

void JsonTraceParser::ParseSystraceLine(int64_t, SystraceLine line) {
  systrace_line_parser_.ParseLine(line);
}

void JsonTraceParser::ParseJsonPacket(int64_t timestamp,
                                      std::string string_value) {
  PERFETTO_DCHECK(json::IsJsonSupported());

#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
  auto opt_value = json::ParseJsonString(base::StringView(string_value));
  if (!opt_value) {
    context_->storage->IncrementStats(stats::json_parser_failure);
    return;
  }

  ProcessTracker* procs = context_->process_tracker.get();
  TraceStorage* storage = context_->storage.get();
  SliceTracker* slice_tracker = context_->slice_tracker.get();
  FlowTracker* flow_tracker = context_->flow_tracker.get();

  const Json::Value& value = *opt_value;
  auto& ph = value["ph"];
  if (!ph.isString())
    return;
  char phase = *ph.asCString();

  std::optional<uint32_t> opt_pid;
  std::optional<uint32_t> opt_tid;

  if (value.isMember("pid"))
    opt_pid = json::CoerceToUint32(value["pid"]);
  if (value.isMember("tid"))
    opt_tid = json::CoerceToUint32(value["tid"]);

  uint32_t pid = opt_pid.value_or(0);
  uint32_t tid = opt_tid.value_or(pid);
  UniqueTid utid = procs->UpdateThread(tid, pid);

  std::string id = value.isMember("id") ? value["id"].asString() : "";

  base::StringView cat = value.isMember("cat")
                             ? base::StringView(value["cat"].asCString())
                             : base::StringView();
  StringId cat_id = storage->InternString(cat);

  base::StringView name = value.isMember("name")
                              ? base::StringView(value["name"].asCString())
                              : base::StringView();
  StringId name_id = name.empty() ? kNullStringId : storage->InternString(name);

  auto args_inserter = [this, &value](ArgsTracker::BoundInserter* inserter) {
    if (value.isMember("args")) {
      json::AddJsonValueToArgs(value["args"], /* flat_key = */ "args",
                               /* key = */ "args", context_->storage.get(),
                               inserter);
    }
  };

  // Only used for 'B', 'E', and 'X' events so wrap in lambda so it gets
  // ignored in other cases. This lambda is only safe to call within the
  // scope of this function due to the capture by reference.
  auto make_slice_row = [&](TrackId track_id) {
    tables::SliceTable::Row row;
    row.ts = timestamp;
    row.track_id = track_id;
    row.category = cat_id;
    row.name = name_id;
    row.thread_ts = json::CoerceToTs(value["tts"]);
    // tdur will only exist on 'X' events.
    row.thread_dur = json::CoerceToTs(value["tdur"]);
    // JSON traces don't report these counters as part of slices.
    row.thread_instruction_count = std::nullopt;
    row.thread_instruction_delta = std::nullopt;
    return row;
  };

  switch (phase) {
    case 'B': {  // TRACE_EVENT_BEGIN.
      TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
      slice_tracker->BeginTyped(storage->mutable_slice_table(),
                                make_slice_row(track_id), args_inserter);
      MaybeAddFlow(track_id, value);
      break;
    }
    case 'E': {  // TRACE_EVENT_END.
      TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
      auto opt_slice_id = slice_tracker->End(timestamp, track_id, cat_id,
                                             name_id, args_inserter);
      // Now try to update thread_dur if we have a tts field.
      auto opt_tts = json::CoerceToTs(value["tts"]);
      if (opt_slice_id.has_value() && opt_tts) {
        auto* slice = storage->mutable_slice_table();
        auto maybe_row = slice->id().IndexOf(*opt_slice_id);
        PERFETTO_DCHECK(maybe_row.has_value());
        auto start_tts = slice->thread_ts()[*maybe_row];
        if (start_tts) {
          slice->mutable_thread_dur()->Set(*maybe_row, *opt_tts - *start_tts);
        }
      }
      break;
    }
    case 'b':
    case 'e':
    case 'n': {
      if (!opt_pid || id.empty()) {
        context_->storage->IncrementStats(stats::json_parser_failure);
        break;
      }
      UniquePid upid = context_->process_tracker->GetOrCreateProcess(pid);
      int64_t cookie = static_cast<int64_t>(base::Hasher::Combine(id.c_str()));
      StringId scope = kNullStringId;
      TrackId track_id = context_->track_tracker->InternLegacyChromeAsyncTrack(
          name_id, upid, cookie, true /* source_id_is_process_scoped */, scope);

      if (phase == 'b') {
        slice_tracker->BeginTyped(storage->mutable_slice_table(),
                                  make_slice_row(track_id), args_inserter);
        MaybeAddFlow(track_id, value);
      } else if (phase == 'e') {
        slice_tracker->End(timestamp, track_id, cat_id, name_id, args_inserter);
        // We don't handle tts here as we do in the 'E'
        // case above as it's not well defined for aysnc slices.
      } else {
        context_->slice_tracker->Scoped(timestamp, track_id, cat_id, name_id,
                                        0);
        MaybeAddFlow(track_id, value);
      }
      break;
    }
    case 'X': {  // TRACE_EVENT (scoped event).
      std::optional<int64_t> opt_dur = json::CoerceToTs(value["dur"]);
      if (!opt_dur.has_value())
        return;
      TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
      auto row = make_slice_row(track_id);
      row.dur = opt_dur.value();
      slice_tracker->ScopedTyped(storage->mutable_slice_table(), std::move(row),
                                 args_inserter);
      MaybeAddFlow(track_id, value);
      break;
    }
    case 'C': {  // TRACE_EVENT_COUNTER
      auto args = value["args"];
      if (!args.isObject()) {
        context_->storage->IncrementStats(stats::json_parser_failure);
        break;
      }

      std::string counter_name_prefix = name.ToStdString();
      if (!id.empty()) {
        counter_name_prefix += " id: " + id;
      }

      for (auto it = args.begin(); it != args.end(); ++it) {
        double counter;
        if (it->isString()) {
          auto opt = base::CStringToDouble(it->asCString());
          if (!opt.has_value()) {
            context_->storage->IncrementStats(stats::json_parser_failure);
            continue;
          }
          counter = opt.value();
        } else if (it->isNumeric()) {
          counter = it->asDouble();
        } else {
          context_->storage->IncrementStats(stats::json_parser_failure);
          continue;
        }
        std::string counter_name = counter_name_prefix + " " + it.name();
        StringId counter_name_id =
            context_->storage->InternString(base::StringView(counter_name));
        context_->event_tracker->PushProcessCounterForThread(
            timestamp, counter, counter_name_id, utid);
      }
      break;
    }
    case 'R':
    case 'I':
    case 'i': {  // TRACE_EVENT_INSTANT
      base::StringView scope;
      if (value.isMember("s")) {
        scope = value["s"].asCString();
      }

      TrackId track_id;
      if (scope == "g") {
        track_id = context_->track_tracker
                       ->GetOrCreateLegacyChromeGlobalInstantTrack();
      } else if (scope == "p") {
        if (!opt_pid) {
          context_->storage->IncrementStats(stats::json_parser_failure);
          break;
        }
        UniquePid upid = context_->process_tracker->GetOrCreateProcess(pid);
        track_id =
            context_->track_tracker->InternLegacyChromeProcessInstantTrack(
                upid);
      } else if (scope == "t" || scope.data() == nullptr) {
        if (!opt_tid) {
          context_->storage->IncrementStats(stats::json_parser_failure);
          break;
        }
        track_id = context_->track_tracker->InternThreadTrack(utid);
        auto row = make_slice_row(track_id);
        row.dur = 0;
        if (row.thread_ts) {
          // Only set thread_dur to zero if we have a thread_ts.
          row.thread_dur = 0;
        }
        slice_tracker->ScopedTyped(storage->mutable_slice_table(),
                                   std::move(row), args_inserter);
        break;
      } else {
        context_->storage->IncrementStats(stats::json_parser_failure);
        break;
      }
      context_->slice_tracker->Scoped(timestamp, track_id, cat_id, name_id, 0,
                                      args_inserter);
      break;
    }
    case 's': {  // TRACE_EVENT_FLOW_START
      TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
      auto opt_source_id =
          MaybeExtractFlowIdentifier(value, /* version2 = */ false);
      if (opt_source_id) {
        FlowId flow_id = flow_tracker->GetFlowIdForV1Event(
            opt_source_id.value(), cat_id, name_id);
        flow_tracker->Begin(track_id, flow_id);
      } else {
        context_->storage->IncrementStats(stats::flow_invalid_id);
      }
      break;
    }
    case 't': {  // TRACE_EVENT_FLOW_STEP
      TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
      auto opt_source_id =
          MaybeExtractFlowIdentifier(value, /* version2 = */ false);
      if (opt_source_id) {
        FlowId flow_id = flow_tracker->GetFlowIdForV1Event(
            opt_source_id.value(), cat_id, name_id);
        flow_tracker->Step(track_id, flow_id);
      } else {
        context_->storage->IncrementStats(stats::flow_invalid_id);
      }
      break;
    }
    case 'f': {  // TRACE_EVENT_FLOW_END
      TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
      auto opt_source_id =
          MaybeExtractFlowIdentifier(value, /* version2 = */ false);
      if (opt_source_id) {
        FlowId flow_id = flow_tracker->GetFlowIdForV1Event(
            opt_source_id.value(), cat_id, name_id);
        bool bind_enclosing_slice =
            value.isMember("bp") && strcmp(value["bp"].asCString(), "e") == 0;
        flow_tracker->End(track_id, flow_id, bind_enclosing_slice,
                          /* close_flow = */ false);
      } else {
        context_->storage->IncrementStats(stats::flow_invalid_id);
      }
      break;
    }
    case 'M': {  // Metadata events (process and thread names).
      if (name == "thread_name" && !value["args"]["name"].empty()) {
        const char* thread_name = value["args"]["name"].asCString();
        auto thread_name_id = context_->storage->InternString(thread_name);
        procs->UpdateThreadName(tid, thread_name_id,
                                ThreadNamePriority::kOther);
        break;
      }
      if (name == "process_name" && !value["args"]["name"].empty()) {
        const char* proc_name = value["args"]["name"].asCString();
        procs->SetProcessMetadata(pid, std::nullopt, proc_name,
                                  base::StringView());
        break;
      }
    }
  }
#else
  perfetto::base::ignore_result(timestamp);
  perfetto::base::ignore_result(context_);
  perfetto::base::ignore_result(string_value);
  PERFETTO_ELOG("Cannot parse JSON trace due to missing JSON support");
#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
}

void JsonTraceParser::MaybeAddFlow(TrackId track_id, const Json::Value& event) {
  PERFETTO_DCHECK(json::IsJsonSupported());
#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
  auto opt_bind_id = MaybeExtractFlowIdentifier(event, /* version2 = */ true);
  if (opt_bind_id) {
    FlowTracker* flow_tracker = context_->flow_tracker.get();
    bool flow_out = event.isMember("flow_out") && event["flow_out"].asBool();
    bool flow_in = event.isMember("flow_in") && event["flow_in"].asBool();
    if (flow_in && flow_out) {
      flow_tracker->Step(track_id, opt_bind_id.value());
    } else if (flow_out) {
      flow_tracker->Begin(track_id, opt_bind_id.value());
    } else if (flow_in) {
      // bind_enclosing_slice is always true for v2 flow events
      flow_tracker->End(track_id, opt_bind_id.value(), true,
                        /* close_flow = */ false);
    } else {
      context_->storage->IncrementStats(stats::flow_without_direction);
    }
  }
#else
  perfetto::base::ignore_result(track_id);
  perfetto::base::ignore_result(event);
#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
}

}  // namespace trace_processor
}  // namespace perfetto
