/*
 * Copyright (C) 2021 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_UTIL_PROTO_TO_ARGS_PARSER_H_
#define SRC_TRACE_PROCESSOR_UTIL_PROTO_TO_ARGS_PARSER_H_

#include <functional>

#include "perfetto/base/status.h"
#include "perfetto/protozero/field.h"
#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
#include "src/trace_processor/util/descriptors.h"

namespace perfetto {
namespace trace_processor {

// TODO(altimin): Move InternedMessageView into trace_processor/util.
class InternedMessageView;
class PacketSequenceStateGeneration;

namespace util {

// ProtoToArgsParser encapsulates the process of taking an arbitrary proto and
// parsing it into key-value arg pairs. This is done by traversing
// the proto using reflection (with descriptors from |descriptor_pool|)
// and passing the parsed data to |Delegate| callbacks.
//
// E.g. given a proto like
//
// package perfetto.protos;
// message SubMessage {
//   optional int32 field = 1;
// }
// message MainMessage {
//   optional int32 field1 = 1;
//   optional string field2 = 2;
//   optional SubMessage field3 = 3;
// }
//
// We will get the args set columns "field1", "field2", "field3.field" and will
// store the values found inside as the result.
//
// Usage of this is as follows:
//
// DescriptorPool pool;
// ProtoToArgsParser parser(pool);
// pool.AddProtoFileDescriptor(
//     /* provide descriptor generated by tools/gen_binary_descriptors */);
// parser.ParseMessage(const_bytes, ".perfetto.protos.MainMessage",
//     /* fields */, /* delegate */);
class ProtoToArgsParser {
 public:
  explicit ProtoToArgsParser(const DescriptorPool& descriptor_pool);

  struct Key {
    Key(const std::string& flat_key, const std::string& key);
    Key(const std::string& key);
    Key();
    ~Key();

    std::string flat_key;
    std::string key;
  };

  class Delegate {
   public:
    virtual ~Delegate();

    virtual void AddInteger(const Key& key, int64_t value) = 0;
    virtual void AddUnsignedInteger(const Key& key, uint64_t value) = 0;
    virtual void AddString(const Key& key,
                           const protozero::ConstChars& value) = 0;
    virtual void AddString(const Key& key, const std::string& value) = 0;
    virtual void AddDouble(const Key& key, double value) = 0;
    virtual void AddPointer(const Key& key, const void* value) = 0;
    virtual void AddBoolean(const Key& key, bool value) = 0;
    // Returns whether an entry was added or not.
    virtual bool AddJson(const Key& key,
                         const protozero::ConstChars& value) = 0;
    virtual void AddNull(const Key& key) = 0;

    virtual size_t GetArrayEntryIndex(const std::string& array_key) = 0;
    virtual size_t IncrementArrayEntryIndex(const std::string& array_key) = 0;

    virtual PacketSequenceStateGeneration* seq_state() = 0;

    virtual int64_t packet_timestamp() { return 0; }

    template <typename FieldMetadata>
    typename FieldMetadata::cpp_field_type::Decoder* GetInternedMessage(
        FieldMetadata,
        uint64_t iid) {
      static_assert(std::is_base_of<protozero::proto_utils::FieldMetadataBase,
                                    FieldMetadata>::value,
                    "Field metadata should be a subclass of FieldMetadataBase");
      static_assert(std::is_same<typename FieldMetadata::message_type,
                                 protos::pbzero::InternedData>::value,
                    "Field should belong to InternedData proto");
      auto* interned_message_view =
          GetInternedMessageView(FieldMetadata::kFieldId, iid);
      if (!interned_message_view)
        return nullptr;
      return interned_message_view->template GetOrCreateDecoder<
          typename FieldMetadata::cpp_field_type>();
    }

   protected:
    virtual InternedMessageView* GetInternedMessageView(uint32_t field_id,
                                                        uint64_t iid) = 0;
  };

  // Given a view of bytes that represent a serialized protozero message of
  // |type| we will parse each field.
  //
  // Returns on any error with a status describing the problem. However any
  // added values before encountering the error will be parsed and forwarded to
  // the delegate.
  //
  // Fields with ids given in |fields| are parsed using reflection, as well
  // as known (previously registered) extension fields. If |allowed_fields| is a
  // nullptr, all fields are going to be parsed.
  //
  // Note:
  // |type| must be the fully qualified name, but with a '.' added to the
  // beginning. I.E. ".perfetto.protos.TrackEvent". And must match one of the
  // descriptors already added through |AddProtoFileDescriptor|.
  //
  // IMPORTANT: currently bytes fields are not supported.
  //
  // TODO(b/145578432): Add support for byte fields.
  base::Status ParseMessage(const protozero::ConstBytes& cb,
                            const std::string& type,
                            const std::vector<uint16_t>* allowed_fields,
                            Delegate& delegate,
                            int* unknown_extensions = nullptr);

  // This class is responsible for resetting the current key prefix to the old
  // value when deleted or reset.
  struct ScopedNestedKeyContext {
   public:
    ~ScopedNestedKeyContext();
    ScopedNestedKeyContext(ScopedNestedKeyContext&&);
    ScopedNestedKeyContext(const ScopedNestedKeyContext&) = delete;
    ScopedNestedKeyContext& operator=(const ScopedNestedKeyContext&) = delete;

    const Key& key() const { return key_; }

    // Clear this context, which strips the latest suffix from |key_| and sets
    // it to the state before the nested context was created.
    void RemoveFieldSuffix();

   private:
    friend class ProtoToArgsParser;

    ScopedNestedKeyContext(Key& old_value);

    struct ScopedStringAppender;

    Key& key_;
    std::optional<size_t> old_flat_key_length_ = std::nullopt;
    std::optional<size_t> old_key_length_ = std::nullopt;
  };

  // These methods can be called from parsing overrides to enter nested
  // contexts. The contexts are left when the returned scope is destroyed or
  // RemoveFieldSuffix() is called.
  ScopedNestedKeyContext EnterDictionary(const std::string& key);
  ScopedNestedKeyContext EnterArray(size_t index);

  using ParsingOverrideForField =
      std::function<std::optional<base::Status>(const protozero::Field&,
                                                Delegate& delegate)>;

  // Installs an override for the field at the specified path. We will invoke
  // |parsing_override| when the field is encountered.
  //
  // The return value of |parsing_override| indicates whether the override
  // parsed the sub-message and ProtoToArgsParser should skip it (std::nullopt)
  // or the sub-message should continue to be parsed by ProtoToArgsParser using
  // the descriptor (base::Status).
  //
  // Note |field_path| must be the full path separated by periods. I.E. in the
  // proto
  //
  // message SubMessage {
  //   optional int32 field = 1;
  // }
  // message MainMessage {
  //   optional SubMessage field1 = 1;
  //   optional SubMessage field2 = 2;
  // }
  //
  // To override the handling of both SubMessage fields you must add two parsing
  // overrides. One with a |field_path| == "field1.field" and another with
  // "field2.field".
  void AddParsingOverrideForField(const std::string& field_path,
                                  ParsingOverrideForField parsing_override);

  using ParsingOverrideForType = std::function<std::optional<base::Status>(
      ScopedNestedKeyContext& key,
      const protozero::ConstBytes& data,
      Delegate& delegate)>;

  // Installs an override for all fields with the given type. We will invoke
  // |parsing_override| when a field with the given message type is encountered.
  // Note that the path-based overrides take precedence over type overrides.
  //
  // The return value of |parsing_override| indicates whether the override
  // parsed the sub-message and ProtoToArgsParser should skip it (std::nullopt)
  // or the sub-message should continue to be parsed by ProtoToArgsParser using
  // the descriptor (base::Status).
  //
  //
  // For example, given the following protos and a type override for SubMessage,
  // all three fields will be parsed using this override.
  //
  // message SubMessage {
  //   optional int32 value = 1;
  // }
  //
  // message MainMessage1 {
  //   optional SubMessage field1 = 1;
  //   optional SubMessage field2 = 2;
  // }
  //
  // message MainMessage2 {
  //   optional SubMessage field3 = 1;
  // }
  void AddParsingOverrideForType(const std::string& message_type,
                                 ParsingOverrideForType parsing_override);

 private:
  base::Status ParseField(const FieldDescriptor& field_descriptor,
                          int repeated_field_number,
                          protozero::Field field,
                          Delegate& delegate,
                          int* unknown_extensions);

  base::Status ParsePackedField(
      const FieldDescriptor& field_descriptor,
      std::unordered_map<size_t, int>& repeated_field_index,
      protozero::Field field,
      Delegate& delegate,
      int* unknown_extensions);

  std::optional<base::Status> MaybeApplyOverrideForField(
      const protozero::Field&,
      Delegate& delegate);

  std::optional<base::Status> MaybeApplyOverrideForType(
      const std::string& message_type,
      ScopedNestedKeyContext& key,
      const protozero::ConstBytes& data,
      Delegate& delegate);

  // A type override can call |key.RemoveFieldSuffix()| if it wants to exclude
  // the overriden field's name from the parsed args' keys.
  base::Status ParseMessageInternal(ScopedNestedKeyContext& key,
                                    const protozero::ConstBytes& cb,
                                    const std::string& type,
                                    const std::vector<uint16_t>* fields,
                                    Delegate& delegate,
                                    int* unknown_extensions);

  base::Status ParseSimpleField(const FieldDescriptor& desciptor,
                                const protozero::Field& field,
                                Delegate& delegate);

  std::unordered_map<std::string, ParsingOverrideForField> field_overrides_;
  std::unordered_map<std::string, ParsingOverrideForType> type_overrides_;
  const DescriptorPool& pool_;
  Key key_prefix_;
};

}  // namespace util
}  // namespace trace_processor
}  // namespace perfetto

#endif  // SRC_TRACE_PROCESSOR_UTIL_PROTO_TO_ARGS_PARSER_H_
