/*
 * 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 "tools/ftrace_proto_gen/ftrace_descriptor_gen.h"

namespace perfetto {

void GenerateFtraceDescriptors(
    const google::protobuf::DescriptorPool& descriptor_pool,
    std::ostream* fout) {
  const google::protobuf::Descriptor* ftrace_event =
      descriptor_pool.FindMessageTypeByName("perfetto.protos.FtraceEvent");
  const google::protobuf::OneofDescriptor* one_of_event =
      ftrace_event->FindOneofByName("event");

  // Find max id for any ftrace event.
  int max_id = 0;
  for (int i = 0; i < one_of_event->field_count(); i++)
    max_id = std::max(max_id, one_of_event->field(i)->number());

  *fout << "// Autogenerated by:\n";
  *fout << std::string("// ") + __FILE__ + "\n";
  *fout << "// Do not edit.\n";
  *fout << R"(
  #include "src/trace_processor/ftrace_descriptors.h"

  namespace perfetto {
  namespace trace_processor {
  namespace {

  std::array<MessageDescriptor,
  )";
  *fout << std::to_string(max_id + 1) + "> descriptors{{";

  for (int i = 0; i <= max_id; i++) {
    const google::protobuf::FieldDescriptor* event =
        ftrace_event->FindFieldByNumber(i);
    // Skip events that don't exist or are not messages. (Proxy for events)
    if (!event ||
        event->type() != google::protobuf::FieldDescriptor::TYPE_MESSAGE) {
      *fout << "{nullptr, 0, {}},";
      continue;
    }

    const auto* event_descriptor = event->message_type();

    // Find the max field id in the event.
    int max_field_id = 0;
    for (int j = 0; j < event_descriptor->field_count(); j++)
      max_field_id =
          std::max(max_field_id, event_descriptor->field(j)->number());

    *fout << "{\"" + event->name() + "\", " << max_field_id << ", "
          << "{";

    for (int j = 0; j <= max_field_id; j++) {
      const auto* field = event_descriptor->FindFieldByNumber(j);
      // Skip fields that don't exist or are nested messages.
      if (!field ||
          field->type() == google::protobuf::FieldDescriptor::TYPE_MESSAGE) {
        *fout << "{},";
        continue;
      }
      ProtoType type = ProtoType::FromDescriptor(field->type());
      *fout << "{\"" + field->name() + "\", ProtoSchemaType::k" +
                   ToCamelCase(type.ToString()) + "},";
    }
    *fout << "},\n},";
  }
  *fout << "}};\n";
  *fout << R"(
  } // namespace

  MessageDescriptor* GetMessageDescriptorForId(size_t id) {
    PERFETTO_CHECK(id < descriptors.size());
    return &descriptors[id];
  }

  size_t GetDescriptorsSize() {
    return descriptors.size();
  }
  )";
  *fout << "} // namespace trace_processor\n} // namespace perfetto\n";
}

}  // namespace perfetto
