// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "apps/benchmark/event.h"

#include <map>
#include <stack>

#include "base/json/json_reader.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"

namespace benchmark {

Event::Event() {}

Event::Event(EventType type,
             std::string name,
             std::string categories,
             base::TimeTicks timestamp,
             base::TimeDelta duration)
    : type(type),
      name(name),
      categories(categories),
      timestamp(timestamp),
      duration(duration) {}

Event::~Event() {}

namespace {
// ID uniquely identifying an asynchronous event stack.
struct AsyncEventStackId {
  std::string id;
  std::string cat;
};

bool operator<(const AsyncEventStackId& t, const AsyncEventStackId& o) {
  return t.id < o.id || (t.id == o.id && t.cat < o.cat);
}

// ID uniquely identifying a duration event stack.
typedef std::string DurationEventStackId;

bool ExtractKeyAsString(base::DictionaryValue* event_dict,
                        const std::string& key,
                        std::string* output) {
  const base::Value* value;
  if (!event_dict->Get(key, &value)) {
    LOG(ERROR) << "Incorrect trace event (missing " + key + "): "
               << *event_dict;
    return false;
  }

  if (value->IsType(base::Value::TYPE_INTEGER)) {
    int id_int = 0;
    // We already verified the type, so it should be an integer.
    CHECK(value->GetAsInteger(&id_int));
    *output = base::IntToString(id_int);
  } else if (value->IsType(base::Value::TYPE_STRING)) {
    CHECK(value->GetAsString(output));
  } else {
    LOG(ERROR) << "Incorrect trace event (" + key +
                      " not a string or integer): "
               << *event_dict;
    return false;
  }
  return true;
}

// Makes a unique id for a duration event stack.
bool GetDurationEventStackId(base::DictionaryValue* event_dict,
                             DurationEventStackId* durationId) {
  return ExtractKeyAsString(event_dict, "tid", durationId);
}

// Makes a unique key for an async event stack.
bool GetAsyncEventStackId(base::DictionaryValue* event_dict,
                          AsyncEventStackId* asyncId) {
  if (!ExtractKeyAsString(event_dict, "id", &asyncId->id)) {
    return false;
  }

  // We can have an empty category, but it is still relevant for event
  // merging per the documentation.
  std::string cat;
  event_dict->GetString("cat", &asyncId->cat);

  return true;
}

// Given a beginning event, registers its beginning for future merging.
template <typename T>
void RegisterEventBegin(
    T key,
    base::DictionaryValue* event_dict,
    std::map<T, std::stack<base::DictionaryValue*>>* open_events) {
  (*open_events)[key].push(event_dict);
}

// Given an end event, merges it with a previously-seen beginning event.
template <typename T>
bool MergeEventEnd(
    T key,
    base::DictionaryValue* event_dict,
    std::map<T, std::stack<base::DictionaryValue*>>* open_events) {
  if (!open_events->count(key) || (*open_events)[key].empty()) {
    LOG(ERROR) << "Incorrect trace event (event end without begin).";
    return false;
  }

  base::DictionaryValue* begin_event_dict = (*open_events)[key].top();
  (*open_events)[key].pop();
  double begin_ts;
  if (!begin_event_dict->GetDouble("ts", &begin_ts)) {
    LOG(ERROR) << "Incorrect trace event (no timestamp)";
    return false;
  }

  double end_ts;
  if (!event_dict->GetDouble("ts", &end_ts)) {
    LOG(ERROR) << "Incorrect trace event (no timestamp)";
    return false;
  }

  if (end_ts < begin_ts) {
    LOG(ERROR) << "Incorrect trace event (event ends before it begins)";
    return false;
  }

  begin_event_dict->SetDouble("dur", end_ts - begin_ts);
  begin_event_dict->SetString("ph", "X");
  return true;
}

// Finds the matching "end" event for each "begin" event of type duration or
// async, and rewrites the "begin event" as a "complete" event with a duration.
// Leaves all events that are not "begin" unchanged.
bool JoinEvents(base::ListValue* event_list) {
  // Maps thread ids to stacks of unmatched duration begin events on the given
  // thread.
  std::map<DurationEventStackId, std::stack<base::DictionaryValue*>>
      open_begin_duration_events;
  std::map<AsyncEventStackId, std::stack<base::DictionaryValue*>>
      open_begin_async_events;

  for (base::Value* val : *event_list) {
    base::DictionaryValue* event_dict;
    if (!val->GetAsDictionary(&event_dict))
      return false;

    std::string phase;
    if (!event_dict->GetString("ph", &phase)) {
      LOG(ERROR) << "Incorrect trace event (missing phase)";
      return false;
    }

    if (phase == "B" || phase == "E") {
      DurationEventStackId durationId;
      if (!GetDurationEventStackId(event_dict, &durationId)) {
        return false;
      }
      if (phase == "B") {
        RegisterEventBegin(durationId, event_dict, &open_begin_duration_events);
      } else if (phase == "E" &&
                 !MergeEventEnd(durationId, event_dict,
                                &open_begin_duration_events)) {
        return false;
      }
    } else if (phase == "b" || phase == "S" || phase == "e" || phase == "F") {
      AsyncEventStackId asyncId;
      if (!GetAsyncEventStackId(event_dict, &asyncId)) {
        return false;
      }
      if (phase == "b" || phase == "S") {
        RegisterEventBegin(asyncId, event_dict, &open_begin_async_events);
      } else if ((phase == "e" || phase == "F") &&
                 !MergeEventEnd(asyncId, event_dict,
                                &open_begin_async_events)) {
        return false;
      }
    }
  }
  return true;
}

bool ParseEvents(base::ListValue* event_list, std::vector<Event>* result) {
  result->clear();

  for (base::Value* val : *event_list) {
    base::DictionaryValue* event_dict;
    if (!val->GetAsDictionary(&event_dict)) {
      LOG(WARNING) << "Ignoring incorrect trace event (not a dictionary)";
      continue;
    }

    Event event;

    std::string phase;
    if (!event_dict->GetString("ph", &phase)) {
      LOG(WARNING) << "Ignoring incorrect trace event (missing phase)";
      continue;
    }
    if (phase == "X") {
      event.type = EventType::COMPLETE;
    } else if (phase == "I" || phase == "n") {
      event.type = EventType::INSTANT;
    } else {
      // Skip all event types we do not handle.
      continue;
    }

    if (!event_dict->GetString("name", &event.name)) {
      LOG(ERROR) << "Incorrect trace event (no name)";
      return false;
    }

    // Some clients do not add categories to events, but we don't want to fail
    // nor skip the event.
    event_dict->GetString("cat", &event.categories);

    double timestamp;
    if (!event_dict->GetDouble("ts", &timestamp)) {
      LOG(WARNING) << "Ingoring incorrect trace event (no timestamp)";
      continue;
    }
    event.timestamp = base::TimeTicks::FromInternalValue(timestamp);

    if (event.type == EventType::COMPLETE) {
      double duration;
      if (!event_dict->GetDouble("dur", &duration)) {
        LOG(WARNING) << "Ignoring incorrect complete event (no duration)";
        continue;
      }

      event.duration = base::TimeDelta::FromInternalValue(duration);
    } else {
      event.duration = base::TimeDelta();
    }

    result->push_back(event);
  }
  return true;
}

}  // namespace

bool GetEvents(const std::string& trace_json, std::vector<Event>* result) {
  // Parse the JSON string describing the events.
  base::JSONReader reader;
  scoped_ptr<base::Value> trace_data = reader.ReadToValue(trace_json);
  if (!trace_data) {
    LOG(ERROR) << "Failed to parse the JSON string: "
               << reader.GetErrorMessage();
    return false;
  }

  base::ListValue* event_list;
  if (!trace_data->GetAsList(&event_list)) {
    LOG(ERROR) << "Incorrect format of the trace data.";
    return false;
  }

  if (!JoinEvents(event_list))
    return false;

  if (!ParseEvents(event_list, result))
    return false;
  return true;
}
}  // namespace benchmark
