// Example program for matching summary functions and synthetic child providers.
//
// The classes here simulate code generated by a serialization tool like, for
// example, protocol buffers. But the actual "generated" class layout is
// extremely naive to simplify the example.
//
// The idea is that we want to have generic formatters for a bunch of message
// classes, because they are all generated following common patterns, but the
// matching can't be based in the type name, because it can be anything.

#include <string>

class Message {
  // Dummy method definitions to illustrate a possible generic message API.
  std::string serialize() { return "TODO"; }
  Message* deserialize() {
    return nullptr;  // TODO.
  }
};

// This class could have been generated from a description like this. Assume
// fields are always optional, for simplicity (e.g. we don't care during
// serialization if a Customer has a name or not, we're just moving data around
// and validation happens elsewhere).
//
// message Customer {
//   string name;
//   int age;
//   string address;
// }
class Customer : public Message {
 private:
  int _internal_bookkeeping_bits_;

  // Presence bits. They are true if the field has been set.
  bool _has_name_ = false;
  bool _has_age_ = false;
  bool _has_address_ = false;

  // Actual field data.
  std::string name_;
  int age_;
  std::string address_;

 public:
  // Getters and setters.
  bool has_name() { return _has_name_; }
  bool has_age() { return _has_age_; }
  bool has_address() { return _has_address_; }

  std::string name() { return name_; }
  int age() { return age_; }
  std::string address() { return address_; }

  void set_name(std::string name) {
    name_ = name;
    _has_name_ = true;
  }
  void set_age(int age) {
    age_ = age;
    _has_age_ = true;
  }
  void set_address(std::string address) {
    address_ = address;
    _has_address_ = true;
  }
};

// message ProductOrder {
//   string product_name;
//   int amount;
// }
class ProductOrder : public Message {
 private:
  int _internal_bookkeeping_bits_;

  // Presence bits. They are true if the field has been set.
  bool _has_product_name_ = false;
  bool _has_amount_ = false;

  // Actual field data.
  std::string product_name_;
  int amount_;

 public:
  // Getters and setters.
  bool has_product_name() { return _has_product_name_; }
  bool has_amount() { return _has_amount_; }

  std::string get_product_name() { return product_name_; }
  int get_amount() { return amount_; }

  void set_product_name(std::string product_name) {
    product_name_ = product_name;
    _has_product_name_ = true;
  }
  void set_amount(int amount) {
    amount_ = amount;
    _has_amount_ = true;
  }
};

int main(int argc, char **argv) {
  Customer customer;
  customer.set_name("C. Ustomer");
  customer.set_address("123 Fake St.");
  // no age, so we can check absent fields get omitted.

  ProductOrder order;
  order.set_product_name("widget");
  order.set_amount(100);
  return 0;  // break here.
}

