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

#ifndef SRC_LIB_FIDL_CODEC_LIBRARY_LOADER_H_
#define SRC_LIB_FIDL_CODEC_LIBRARY_LOADER_H_

#include <zircon/assert.h>

#include <map>
#include <memory>
#include <string>
#include <vector>

#include <rapidjson/document.h>

#include "src/lib/fidl_codec/semantic.h"

// This file contains a programmatic representation of a FIDL schema.  A
// LibraryLoader loads a set of Libraries.  The libraries contain structs,
// enums, protocols, and so on.  Each element has the logic necessary to take
// wire-encoded bits of that type, and transform it to a representation of that
// type.

// A LibraryLoader object can be used to fetch a particular library or protocol
// method, which can then be used for debug purposes.

// An example of building a LibraryLoader can be found in
// library_loader_test.cc:LoadSimple. Callers can then do something like the
// following, if they have a fidl::Message:
//
// fidl_message_header_t header = message.header();
// const std::vector<ProtocolMethod*>* methods = loader_->GetByOrdinal(header.ordinal);
// rapidjson::Document actual;
// fidl_codec::RequestToJSON(methods->at(0), message, actual);
//
// |actual| will then contain the contents of the message in JSON
// (human-readable) format.
//
// These libraries are currently thread-unsafe.

namespace fidl_codec {

constexpr int kDecimalBase = 10;

using Ordinal32 = uint32_t;
using Ordinal64 = uint64_t;

enum class WireVersion : uint8_t { kWireV2 };

struct LibraryReadError {
  enum ErrorValue : uint8_t {
    kOk,
    kIoError,
    kParseError,
  };
  ErrorValue value;
  // Unset unless `value` == kIoError.
  int errno_value;
  rapidjson::ParseResult parse_result;
};

class Protocol;
class ProtocolMethod;
class Payload;
class Library;
class LibraryLoader;
class MessageDecoder;
class Struct;
class StructValue;
class Table;
class TypeVisitor;
class Union;
class Int32Type;

class EnumOrBitsMember {
  friend class Enum;
  friend class Bits;

 public:
  EnumOrBitsMember(const std::string_view& name, uint64_t absolute_value, bool negative)
      : name_(name), absolute_value_(absolute_value), negative_(negative) {}

  const std::string& name() const { return name_; }
  uint64_t absolute_value() const { return absolute_value_; }
  bool negative() const { return negative_; }

 private:
  const std::string name_;
  const uint64_t absolute_value_;
  const bool negative_;
};

class EnumOrBits {
 public:
  friend class Library;

  ~EnumOrBits();

  const std::string& name() const { return name_; }
  uint64_t size() const { return size_; }
  const Type* type() const { return type_.get(); }

  // Get a list of Enum members.
  const std::vector<EnumOrBitsMember>& members() const { return members_; }

  uint64_t Size(WireVersion version) const { return size_; }

 protected:
  EnumOrBits(std::string name, uint64_t size_v2, std::unique_ptr<Type> type,
             std::vector<EnumOrBitsMember> members);
  explicit EnumOrBits(const rapidjson::Value* json_definition);
  // Decode all the values from the JSON definition.
  void DecodeTypes(bool is_scalar, const std::string& supertype_name, Library* enclosing_library);

 private:
  const rapidjson::Value* json_definition_;
  std::string name_;
  uint64_t size_;
  std::unique_ptr<Type> type_;
  std::vector<EnumOrBitsMember> members_;
};

class Enum : public EnumOrBits {
 public:
  friend class Library;
  // Gets the name of the enum member corresponding to the value pointed to by
  // |bytes| of length |length|.  For example, if we had the following
  // definition:
  // enum i16_enum : int16 {
  //   x = -23;
  // };
  // and you pass |bytes| a 2-byte representation of -23, and |length| 2, this
  // function will return "x".  Returns "(Unknown enum member)" if it can't find
  // the member.
  std::string GetName(uint64_t absolute_value, bool negative) const;

  static const Enum& FrameworkErrorEnum();

 private:
  Enum(std::string name, uint64_t size, std::unique_ptr<Type> type,
       std::vector<EnumOrBitsMember> members);
  explicit Enum(const rapidjson::Value* json_definition) : EnumOrBits(json_definition) {}

  void DecodeTypes(Library* enclosing_library) {
    return EnumOrBits::DecodeTypes(true, "enum", enclosing_library);
  }
};

class Bits : public EnumOrBits {
 public:
  friend class Library;

  std::string GetName(uint64_t absolute_value, bool negative) const;

 private:
  explicit Bits(const rapidjson::Value* json_definition) : EnumOrBits(json_definition) {}

  void DecodeTypes(Library* enclosing_library) {
    return EnumOrBits::DecodeTypes(false, "bits", enclosing_library);
  }
};

class UnionMember {
 public:
  UnionMember(const Union& union_definition, Library* enclosing_library,
              const rapidjson::Value* json_definition);

  const Union& union_definition() const { return union_definition_; }
  const std::string& name() const { return name_; }
  Ordinal64 ordinal() const { return ordinal_; }
  const Type* type() const { return type_.get(); }

 private:
  const Union& union_definition_;
  const std::string name_;
  const Ordinal64 ordinal_;
  std::unique_ptr<Type> type_;
};

class Union final {
 public:
  friend class Library;

  Library* enclosing_library() const { return enclosing_library_; }
  const std::string& name() const { return name_; }
  const std::vector<std::unique_ptr<UnionMember>>& members() const { return members_; }

  const UnionMember* MemberFromOrdinal(Ordinal64 ordinal) const;
  UnionMember* SearchMember(std::string_view name) const;
  std::string ToString(bool expand) const;

 private:
  Union(Library* enclosing_library, const rapidjson::Value* json_definition);

  // Decode all the values from the JSON definition.
  void DecodeTypes();

  Library* enclosing_library_;
  const rapidjson::Value* json_definition_;
  std::string name_;
  std::vector<std::unique_ptr<UnionMember>> members_;
};

class StructMember {
 public:
  StructMember(Library* enclosing_library, const rapidjson::Value* json_definition);
  StructMember(std::string_view name, std::unique_ptr<Type> type);
  StructMember(std::string_view name, std::unique_ptr<Type> type, uint8_t id);

  const std::string& name() const { return name_; }
  Type* type() const { return type_.get(); }
  void reset_type();
  uint8_t id() const { return id_; }

  uint64_t Offset(WireVersion version) const { return offset_; }

 private:
  const std::string name_;
  uint64_t offset_ = 0;
  std::unique_ptr<Type> type_;
  uint8_t id_ = 0;
};

class Struct final {
 public:
  friend class Library;

  explicit Struct(std::string_view name);

  Library* enclosing_library() const { return enclosing_library_; }
  const std::string& name() const { return name_; }
  const std::vector<std::unique_ptr<StructMember>>& members() const { return members_; }

  void AddMember(std::string_view name, std::unique_ptr<Type> type, uint32_t id = 0);
  StructMember* SearchMember(std::string_view name, uint32_t id = 0) const;
  uint32_t Size(WireVersion version) const;
  std::string ToString(bool expand) const;

 private:
  Struct(Library* enclosing_library, const rapidjson::Value* json_definition);

  // Decode all the values from the JSON definition.
  void DecodeTypes();

  Library* enclosing_library_;
  const rapidjson::Value* json_definition_;
  std::string name_;
  uint32_t size_ = 0;
  std::vector<std::unique_ptr<StructMember>> members_;
};

class TableMember {
 public:
  TableMember(Library* enclosing_library, const rapidjson::Value* json_definition);

  const std::string& name() const { return name_; }
  Ordinal32 ordinal() const { return ordinal_; }
  const Type* type() const { return type_.get(); }

 private:
  const std::string name_;
  const Ordinal32 ordinal_;
  std::unique_ptr<Type> type_;
};

class Table final {
 public:
  friend class Library;

  Library* enclosing_library() const { return enclosing_library_; }
  const std::string& name() const { return name_; }
  const std::vector<std::unique_ptr<TableMember>>& members() const { return members_; }

  const TableMember* MemberFromOrdinal(Ordinal64 ordinal) const;
  const TableMember* SearchMember(std::string_view name) const;
  std::string ToString(bool expand) const;

 private:
  Table(Library* enclosing_library, const rapidjson::Value* json_definition);

  // Decode all the values from the JSON definition.
  void DecodeTypes();

  Library* enclosing_library_;
  const rapidjson::Value* json_definition_;
  std::string name_;
  std::vector<std::unique_ptr<TableMember>> members_;
};

class ProtocolMethod {
 public:
  friend class Protocol;

  ProtocolMethod() = default;
  ~ProtocolMethod();

  const Protocol& enclosing_protocol() const { return *enclosing_protocol_; }
  const std::string& name() const { return name_; }
  Ordinal64 ordinal() const { return ordinal_; }
  bool is_composed() const { return is_composed_; }
  bool has_request() const { return has_request_; }
  bool has_response() const { return has_response_; }
  const Type* request() const { return request_.get(); }
  const Type* response() const { return response_.get(); }

  semantic::MethodSemantic* semantic() { return semantic_.get(); }
  const semantic::MethodSemantic* semantic() const { return semantic_.get(); }
  void set_semantic(std::unique_ptr<semantic::MethodSemantic> semantic) {
    semantic_ = std::move(semantic);
  }

  semantic::MethodDisplay* short_display() { return short_display_.get(); }
  const semantic::MethodDisplay* short_display() const { return short_display_.get(); }
  void set_short_display(std::unique_ptr<semantic::MethodDisplay> short_display) {
    short_display_ = std::move(short_display);
  }

  std::string fully_qualified_name() const;

  void DecodeTypes();

  ProtocolMethod(const ProtocolMethod& other) = delete;
  ProtocolMethod& operator=(const ProtocolMethod&) = delete;

 private:
  ProtocolMethod(Library* enclosing_library, const Protocol& protocol,
                 const rapidjson::Value* json_definition);

  const rapidjson::Value* json_definition_ = nullptr;
  const Protocol* const enclosing_protocol_ = nullptr;
  const std::string name_;
  const Ordinal64 ordinal_ = 0;
  const bool is_composed_ = false;
  bool has_request_ = false;
  std::unique_ptr<Type> request_ = nullptr;
  bool has_response_ = false;
  std::unique_ptr<Type> response_ = nullptr;
  std::unique_ptr<semantic::MethodSemantic> semantic_;
  std::unique_ptr<semantic::MethodDisplay> short_display_;
};

class Protocol {
 public:
  friend class Library;

  Protocol(const Protocol& other) = delete;
  Protocol& operator=(const Protocol&) = delete;

  Library* enclosing_library() const { return enclosing_library_; }
  const std::string& name() const { return name_; }

  void AddMethodsToIndex(LibraryLoader* library_loader);

  // Sets *|method| to the fully qualified |name|'s ProtocolMethod (protocol.method).
  bool GetMethodByFullName(const std::string& name, const ProtocolMethod** method) const;

  ProtocolMethod* GetMethodByName(std::string_view name) const;

  const std::vector<std::unique_ptr<ProtocolMethod>>& methods() const { return protocol_methods_; }

 private:
  Protocol(Library* enclosing_library, const rapidjson::Value& json_definition)
      : enclosing_library_(enclosing_library), name_(json_definition["name"].GetString()) {
    for (auto& method : json_definition["methods"].GetArray()) {
      protocol_methods_.emplace_back(new ProtocolMethod(enclosing_library, *this, &method));
    }
  }

  Library* enclosing_library_;
  std::string name_;
  std::vector<std::unique_ptr<ProtocolMethod>> protocol_methods_;
};

class Library {
 public:
  friend class LibraryLoader;

  LibraryLoader* enclosing_loader() const { return enclosing_loader_; }
  const std::string& name() const { return name_; }

  // The source file path from which this library has been loaded. Will be returned as it was
  // entered when `AddPath` or `AddContent` was called, so if it is a relative path or absolute path
  // it will remain as such.
  const std::string& source() const { return source_; }
  const std::vector<std::unique_ptr<Protocol>>& protocols() const { return protocols_; }

  // Decode all the values from the JSON definition.
  void DecodeTypes();

  // Decode all the content of this FIDL file.
  bool DecodeAll();

  std::unique_ptr<Type> TypeFromIdentifier(bool is_nullable, const std::string& identifier);

  // The size of the type with name |identifier| when it is inline (e.g.,
  // embedded in an array)
  size_t InlineSizeFromIdentifier(std::string& identifier) const;

  // Set *ptr to the Protocol called |name|
  bool GetProtocolByName(std::string_view name, Protocol** ptr) const;

  // Extract a boolean field from a JSON value.
  bool ExtractBool(const rapidjson::Value* json_definition, std::string_view container_type,
                   std::string_view container_name, const char* field_name);
  // Extract a string field from a JSON value.
  std::string ExtractString(const rapidjson::Value* json_definition,
                            std::string_view container_type, std::string_view container_name,
                            const char* field_name);
  // Extract a uint64_t field from a JSON value.
  uint64_t ExtractUint64(const rapidjson::Value* json_definition, std::string_view container_type,
                         std::string_view container_name, const char* field_name);
  // Extract a uint32_t field from a JSON value.
  uint32_t ExtractUint32(const rapidjson::Value* json_definition, std::string_view container_type,
                         std::string_view container_name, const char* field_name);
  // Extract a scalar type from a JSON value.
  std::unique_ptr<Type> ExtractScalarType(const rapidjson::Value* json_definition,
                                          std::string_view container_type,
                                          std::string_view container_name, const char* field_name);
  // Extract a type from a JSON value.
  std::unique_ptr<Type> ExtractType(const rapidjson::Value* json_definition,
                                    std::string_view container_type,
                                    std::string_view container_name, const char* field_name);
  // Extract field offset.
  uint64_t ExtractFieldOffset(const rapidjson::Value* json_definition,
                              std::string_view container_type, std::string_view container_name,
                              const char* field_name);
  // Display an error when a field is not found.
  void FieldNotFound(std::string_view container_type, std::string_view container_name,
                     const char* field_name);

  const Table* GetTable(const std::string& table_name) const {
    auto result = tables_.find(table_name);
    if (result == tables_.end()) {
      return nullptr;
    }
    return result->second.get();
  }

  Library& operator=(const Library&) = delete;
  Library(const Library&) = delete;
  ~Library();

 private:
  Library(std::string source, LibraryLoader* enclosing_loader,
          rapidjson::Document& json_definition);

  LibraryLoader* enclosing_loader_;
  rapidjson::Document json_definition_;
  bool decoded_ = false;
  bool has_errors_ = false;
  std::string name_;
  std::string source_;
  std::vector<std::unique_ptr<Protocol>> protocols_;
  std::map<std::string, std::unique_ptr<Enum>> enums_;
  std::map<std::string, std::unique_ptr<Bits>> bits_;
  std::map<std::string, std::unique_ptr<Union>> unions_;
  std::map<std::string, std::unique_ptr<Struct>> structs_;
  std::map<std::string, std::unique_ptr<Table>> tables_;
};

// An indexed collection of libraries.
// WARNING: All references on Enum, Struct, Table, ... and all references on
//          types and fields must be destroyed before this class (LibraryLoader
//          should be one of the last objects we destroy).
class LibraryLoader {
 public:
  friend class Library;
  // Creates a LibraryLoader populated by the given library paths.
  LibraryLoader(const std::vector<std::string>& library_paths, LibraryReadError* err);

  // Creates a LibraryLoader with no libraries
  LibraryLoader() = default;

  LibraryLoader& operator=(const LibraryLoader&) = delete;
  LibraryLoader(const LibraryLoader&) = delete;

  // Add the libraries for all the paths.
  bool AddAll(const std::vector<std::string>& library_paths, LibraryReadError* err);

  // Decode all the FIDL files.
  bool DecodeAll();

  // Adds a single library to this Loader given its path. Sets err as appropriate.
  void AddPath(const std::string& path, LibraryReadError* err);

  // Adds a single library to this Loader given its content (the JSON text).
  // Sets err as appropriate. The optional `source` field denotes the location from which the
  // file was loaded, and is expected to be formatted as a file system path.
  void AddContent(const std::string& content, LibraryReadError* err, std::string source = "");

  // Adds a method ordinal to the ordinal map.
  void AddMethod(ProtocolMethod* method);

  void ParseBuiltinSemantic();

  // Returns a pointer to a set of methods that have this ordinal.  There may be
  // more than one if the method was composed into multiple protocols.  For
  // convenience, the methods that are not composed are at the front of the
  // vector.  Returns |nullptr| if there is no such method.  The returned
  // pointer continues to be owned by the LibraryLoader, and should not be
  // deleted.
  const std::vector<ProtocolMethod*>* GetByOrdinal(Ordinal64 ordinal) {
    auto m = ordinal_map_.find(ordinal);
    if (m != ordinal_map_.end()) {
      auto methods_for_ordinal = m->second.get();
      for (auto& method : *methods_for_ordinal) {
        method->DecodeTypes();
      }
      return methods_for_ordinal;
    }
    return nullptr;
  }

  // If the library with name |name| is present in this loader, returns the
  // library. Otherwise, returns null.
  // |name| is of the format "a.b.c"
  Library* GetLibraryFromName(const std::string& name) {
    auto l = representations_.find(name);
    if (l != representations_.end()) {
      Library* library = l->second.get();
      library->DecodeTypes();
      return library;
    }
    return nullptr;
  }

 private:
  void Delete(const Library* library) {
    // The only way to delete a library is to remove it from representations_, so we don't need to
    // do that explicitly.  However...
    for (const auto& iface : library->protocols()) {
      for (const auto& method : iface->methods()) {
        ordinal_map_.erase(method->ordinal());
      }
    }
  }

  // Because Delete() above is run whenever a Library is destructed, we want ordinal_map_ to be
  // intact when a Library is destructed.  Therefore, ordinal_map_ has to come first.
  std::map<Ordinal64, std::unique_ptr<std::vector<ProtocolMethod*>>> ordinal_map_;
  std::map<std::string, std::unique_ptr<Library>> representations_;
};

}  // namespace fidl_codec

#endif  // SRC_LIB_FIDL_CODEC_LIBRARY_LOADER_H_
