// Copyright 2018 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.

#pragma once

#include <stdint.h>

#include <functional>
#include <memory>
#include <vector>

#include "garnet/bin/zxdb/console/output_buffer.h"
#include "garnet/bin/zxdb/expr/format_expr_value_options.h"
#include "lib/fxl/memory/ref_counted.h"
#include "lib/fxl/memory/ref_ptr.h"
#include "lib/fxl/memory/weak_ptr.h"

namespace zxdb {

class Collection;
class Enumeration;
class Err;
class ExprValue;
class Location;
class MemberPtr;
class OutputBuffer;
class SymbolContext;
class SymbolDataProvider;
class SymbolVariableResolver;
class Type;
class Value;
class Variable;

// Manages formatting of variables and ExprValues (the results of expressions).
// Since formatting is asynchronous this can be tricky. This class manages a
// set of output operations interleaved with synchronously and asynchronously
// formatted values.
//
// When all requested formatting is complete, the callback will be issued with
// the concatenated result.
//
// When all output is done being appended, call Complete() to schedule the
// final callback.
//
// In common usage the helper can actually be owned by the callback to keep it
// alive during processing and automatically delete it when done:
//
//   auto helper = fxl::MakeRefCounted<FormatValue>();
//   helper->Append(...);
//   // IMPORTANT: Do not move helper into this call or the RefPtr can get
//   // cleared before invoking the call!
//   helper->Complete([helper](OutputBuffer out) { UseIt(out); });
class FormatValue : public fxl::RefCountedThreadSafe<FormatValue> {
 public:
  // Abstruct interface for looking up information about a process.
  class ProcessContext {
   public:
    virtual ~ProcessContext() = default;

    // Given an address in the process, returns the (symbolized if possible)
    // Location for that address.
    virtual Location GetLocationForAddress(uint64_t address) const = 0;
  };

  using Callback = std::function<void(OutputBuffer)>;

  // Construct with fxl::MakeRefCounted<FormatValue>().

  void AppendValue(fxl::RefPtr<SymbolDataProvider> data_provider,
                   const ExprValue value,
                   const FormatExprValueOptions& options);

  // The data provider normally comes from the frame where you want to evaluate
  // the variable in. This will prepend "<name> = " to the value of the
  // variable.
  void AppendVariable(const SymbolContext& symbol_context,
                      fxl::RefPtr<SymbolDataProvider> data_provider,
                      const Variable* var,
                      const FormatExprValueOptions& options);

  void Append(std::string str);
  void Append(OutputBuffer out);

  // Call after all data has been appended.
  //
  // This needs to be a separate call since not all output is asynchronous, and
  // we don't want to call a callback before everything is complete, or not at
  // all.
  void Complete(Callback callback);

 private:
  FRIEND_REF_COUNTED_THREAD_SAFE(FormatValue);
  FRIEND_MAKE_REF_COUNTED(FormatValue);

  enum class NodeType { kGeneric, kVariable, kBaseClass };

  // Output is multilevel and each level can be asynchronous (a struct can
  // include another struct which can include an array, etc.).
  //
  // As we build up the formatted output, each composite type
  // (struct/class/array) adds a new node with its contents as children.
  // Asynchronous operations can fill in the buffers of these nodes, and when
  // all output is complete, the tree can be flattened to produce the final
  // result.
  //
  // REFACTORING IN PROGRESS...
  //
  // Originally OutputNode just held an OutputBuffer in a hierarchical way
  // that can be referenced externally as an OutputKey. Strings were filled in
  // by the value formatter as it went.
  //
  // We would like to move to a design where value formatting is split in two
  // parts: (1) computing a tree of values, (2) converting that tree to text.
  // The first part should be in the client or expr directory, while the text
  // formatting should be in the console directory.
  //
  // With this split, we can drive other types of UIs without duplicating the
  // complex type deduction and stringification logic. Even with the console
  // output only, this design would let us do smarter wrapping since the
  // complete result is known at text-generation time.
  //
  // This class will morph into the tree node. Currently it is a bit of a
  // hybrid where it can store a higher level concept (given by NodeType) with
  // an optional name, or it can just be random text.
  struct OutputNode {
    // Optional.
    std::string name;
    NodeType type = NodeType::kGeneric;

    OutputBuffer buffer;  // Only used when there are no children.

    // Used for sanity checking. This is set when waiting on async resolution
    // on a given node, and cleared when async resolution is complete. It
    // makes sure we don't miss or double-set anything.
    bool pending = false;

    // The children must be heap-allocated because the pointers (in the form of
    // an OutputKey) will be passed around across vector resizes.
    std::vector<std::unique_ptr<OutputNode>> child;
  };

  // Identifies an output buffer to write asynchronously to.
  //
  // This is actually an OutputNode*. The tricky thing is that the pointers
  // are all owned by the FormatValue class. If the class goes out of scope
  // the pointers will be invalidated, but they may still be referenced by
  // in-progress callbacks.
  //
  // To avoid the temptation to write to the OutputBuffer directly from these
  // callbacks, or to forget to check for completion, this type requires a
  // cast. OutputKeyComplete does the cast and checks whether all callbacks are
  // complete. By being on the object itself, it forces asynchronous callbacks
  // to resolve their weak back-pointers first.
  //
  // No code should ever case this other than the functions that manipulate the
  // keys (AppendToOutputKey, AsyncAppend, OutputKeyComplete).
  using OutputKey = intptr_t;

  explicit FormatValue(std::unique_ptr<ProcessContext> process_context);
  ~FormatValue();

  // Formats the given expression value to the output buffer. The variant that
  // takes an Err will do an error check before printing the value, and will
  // output the appropriate error message instead if there is one. It will
  // modify the error message to be appropriate as a replacement for a value.
  // output the appropriate error message instead if there is one.
  //
  // When set, suppress_type_printing will suppress the use of
  // options.always_show_types for this item only (but not nested items). This
  // is designed to be used when called recursively and the type has already
  // been printed.
  void FormatExprValue(fxl::RefPtr<SymbolDataProvider> data_provider,
                       const ExprValue& value,
                       const FormatExprValueOptions& options,
                       bool suppress_type_printing, OutputKey output_key);
  void FormatExprValue(fxl::RefPtr<SymbolDataProvider> data_provider,
                       const Err& err, const ExprValue& value,
                       const FormatExprValueOptions& options,
                       bool suppress_type_printing, OutputKey output_key);

  // Asynchronously formats the given type.
  //
  // The known_elt_count can be -1 if the array size is not statically known.
  void FormatCollection(fxl::RefPtr<SymbolDataProvider> data_provider,
                        const Collection* coll, const ExprValue& value,
                        const FormatExprValueOptions& options,
                        OutputKey output_key);
  void FormatString(fxl::RefPtr<SymbolDataProvider> data_provider,
                    const ExprValue& value, const Type* array_value_type,
                    int known_elt_count, const FormatExprValueOptions& options,
                    OutputKey output_key);

  // Checks array and string types and formats the value accordingly. Returns
  // true if it was an array or string type that was handled, false if it
  // was anything else.
  bool TryFormatArrayOrString(fxl::RefPtr<SymbolDataProvider> data_provider,
                              const Type* type, const ExprValue& value,
                              const FormatExprValueOptions& options,
                              OutputKey output_key);

  // Array and string format helpers.
  void FormatCharPointer(fxl::RefPtr<SymbolDataProvider> data_provider,
                         const Type* type, const ExprValue& value,
                         const FormatExprValueOptions& options,
                         OutputKey output_key);
  void FormatCharArray(const uint8_t* data, size_t length, bool truncated,
                       OutputKey output_key);
  void FormatArray(fxl::RefPtr<SymbolDataProvider> data_provider,
                   const ExprValue& value, int elt_count,
                   const FormatExprValueOptions& options, OutputKey output_key);

  // Dispatcher for all numeric types. This handles formatting overrides.
  void FormatNumeric(const ExprValue& value,
                     const FormatExprValueOptions& options, OutputBuffer* out);

  // Simpler synchronous outputs.
  void FormatBoolean(const ExprValue& value, OutputBuffer* out);
  void FormatEnum(const ExprValue& value, const Enumeration* enum_type,
                  const FormatExprValueOptions& options, OutputBuffer* out);
  void FormatFloat(const ExprValue& value, OutputBuffer* out);
  void FormatSignedInt(const ExprValue& value, OutputBuffer* out);
  void FormatUnsignedInt(const ExprValue& value,
                         const FormatExprValueOptions& options,
                         OutputBuffer* out);
  void FormatChar(const ExprValue& value, OutputBuffer* out);
  void FormatPointer(const ExprValue& value,
                     const FormatExprValueOptions& options, OutputBuffer* out);
  void FormatReference(fxl::RefPtr<SymbolDataProvider> data_provider,
                       const ExprValue& value,
                       const FormatExprValueOptions& options,
                       OutputKey output_key);
  void FormatFunctionPointer(const ExprValue& value,
                             const FormatExprValueOptions& options,
                             OutputBuffer* out);
  void FormatMemberPtr(const ExprValue& value, const MemberPtr* type,
                       const FormatExprValueOptions& options,
                       OutputBuffer* out);

  OutputKey GetRootOutputKey();

  // Appends a child node to the output key without opening an async
  // transaction.
  void AppendToOutputKey(OutputKey output_key, OutputBuffer buffer);

  // An asynchronous version of AppendToOutputKey. The returned key is a
  // sub-key for use in later appending. Call OutputKeyComplete when this is
  // done.
  OutputKey AsyncAppend(OutputKey parent);
  OutputKey AsyncAppend(NodeType type, std::string name, OutputKey parent);

  // Marks the given output key complete. The variant that takes an output
  // buffer is a shorthand for appending the contents and marking it complete.
  // This will check for completion and issue the callback if everything has
  // been resolved.
  void OutputKeyComplete(OutputKey key);
  void OutputKeyComplete(OutputKey key, OutputBuffer contents);

  // Issues the pending callback if necessary. The callback may delete |this|
  // so the caller should immediately return after calling.
  void CheckPendingResolution();

  // Recursively walks the OutputNode tree to produce the final output in
  // the given output buffer. The sources are moved from so this is
  // destructive.
  void RecursiveCollectOutput(OutputNode* node, OutputBuffer* out);

  std::unique_ptr<ProcessContext> process_context_;
  Callback complete_callback_;
  std::vector<OutputBuffer> buffers_;

  std::vector<std::unique_ptr<SymbolVariableResolver>> resolvers_;

  // The root of the output.
  OutputNode root_;

  int pending_resolution_ = 0;

  fxl::WeakPtrFactory<FormatValue> weak_factory_;
};

}  // namespace zxdb
