/*
 * Copyright (C) 2019 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.
 */

#ifndef SRC_TRACE_PROCESSOR_DESCRIPTORS_H_
#define SRC_TRACE_PROCESSOR_DESCRIPTORS_H_

#include <algorithm>
#include <string>
#include <vector>

#include "perfetto/ext/base/optional.h"
#include "perfetto/trace_processor/basic_types.h"
#include "perfetto/trace_processor/status.h"

namespace protozero {
struct ConstBytes;
}

namespace perfetto {
namespace trace_processor {

class FieldDescriptor {
 public:
  FieldDescriptor(std::string name,
                  uint32_t number,
                  uint32_t type,
                  std::string raw_type_name,
                  bool is_repeated);

  const std::string& name() const { return name_; }
  uint32_t number() const { return number_; }
  uint32_t type() const { return type_; }
  const std::string& raw_type_name() const { return raw_type_name_; }
  const std::string& resolved_type_name() const { return resolved_type_name_; }
  bool is_repeated() const { return is_repeated_; }

  void set_resolved_type_name(const std::string& resolved_type_name) {
    resolved_type_name_ = resolved_type_name;
  }

 private:
  std::string name_;
  uint32_t number_;
  uint32_t type_;
  std::string raw_type_name_;
  std::string resolved_type_name_;
  bool is_repeated_;
};

class ProtoDescriptor {
 public:
  enum class Type { kEnum = 0, kMessage = 1 };

  ProtoDescriptor(std::string package_name,
                  std::string full_name,
                  Type type,
                  base::Optional<uint32_t> parent_id);

  void AddField(FieldDescriptor descriptor) {
    PERFETTO_DCHECK(type_ == Type::kMessage);
    fields_.emplace_back(std::move(descriptor));
  }

  void AddEnumValue(int32_t integer_representation,
                    std::string string_representation) {
    PERFETTO_DCHECK(type_ == Type::kEnum);
    enum_values_.emplace_back(integer_representation,
                              std::move(string_representation));
  }

  base::Optional<uint32_t> FindFieldIdxByName(const std::string& name) const {
    PERFETTO_DCHECK(type_ == Type::kMessage);
    auto it = std::find_if(
        fields_.begin(), fields_.end(),
        [name](const FieldDescriptor& desc) { return desc.name() == name; });
    auto idx = static_cast<uint32_t>(std::distance(fields_.begin(), it));
    return idx < fields_.size() ? base::Optional<uint32_t>(idx) : base::nullopt;
  }

  base::Optional<uint32_t> FindFieldIdxByTag(const uint16_t tag_number) const {
    PERFETTO_DCHECK(type_ == Type::kMessage);
    auto it = std::find_if(fields_.begin(), fields_.end(),
                           [tag_number](const FieldDescriptor& desc) {
                             return desc.number() == tag_number;
                           });
    auto idx = static_cast<uint32_t>(std::distance(fields_.begin(), it));
    return idx < fields_.size() ? base::Optional<uint32_t>(idx) : base::nullopt;
  }

  base::Optional<std::string> FindEnumString(const int32_t value) const {
    PERFETTO_DCHECK(type_ == Type::kEnum);
    auto it =
        std::find_if(enum_values_.begin(), enum_values_.end(),
                     [value](const std::pair<int32_t, std::string>& enum_val) {
                       return enum_val.first == value;
                     });
    return it == enum_values_.end() ? base::nullopt
                                    : base::Optional<std::string>(it->second);
  }

  const std::string& package_name() const { return package_name_; }

  const std::string& full_name() const { return full_name_; }

  const std::vector<FieldDescriptor>& fields() const { return fields_; }
  std::vector<FieldDescriptor>* mutable_fields() { return &fields_; }

 private:
  std::string package_name_;
  std::string full_name_;
  const Type type_;
  base::Optional<uint32_t> parent_id_;
  std::vector<FieldDescriptor> fields_;
  std::vector<std::pair<int32_t, std::string>> enum_values_;
};

class DescriptorPool {
 public:
  util::Status AddFromFileDescriptorSet(
      const uint8_t* file_descriptor_set_proto,
      size_t size);

  base::Optional<uint32_t> FindDescriptorIdx(
      const std::string& full_name) const;

  const std::vector<ProtoDescriptor>& descriptors() const {
    return descriptors_;
  }

 private:
  void AddNestedProtoDescriptors(const std::string& package_name,
                                 base::Optional<uint32_t> parent_idx,
                                 protozero::ConstBytes descriptor_proto);
  void AddEnumProtoDescriptors(const std::string& package_name,
                               base::Optional<uint32_t> parent_idx,
                               protozero::ConstBytes descriptor_proto);

  util::Status AddExtensionField(const std::string& package_name,
                                 protozero::ConstBytes field_desc_proto);

  // Recursively searches for the given short type in all parent messages
  // and packages.
  base::Optional<uint32_t> ResolveShortType(const std::string& parent_path,
                                            const std::string& short_type);

  std::vector<ProtoDescriptor> descriptors_;
};

}  // namespace trace_processor
}  // namespace perfetto

#endif  // SRC_TRACE_PROCESSOR_DESCRIPTORS_H_
