/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file LICENSE.rst or https://cmake.org/licensing for details.  */
#pragma once

#include "cmConfigure.h" // IWYU pragma: keep

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

#include <cm3p/json/reader.h>
#include <cm3p/json/value.h>
#include <cm3p/json/writer.h>

class cmake;

class cmFileAPI
{
public:
  cmFileAPI(cmake* cm);

  /** Read fileapi queries from disk.  */
  void ReadQueries();

  /** Get the list of configureLog object kind versions requested.  */
  std::vector<unsigned long> GetConfigureLogVersions();

  /** Identify the situation in which WriteReplies is called.  */
  enum class IndexFor
  {
    Success,
    FailedConfigure,
    FailedCompute,
    FailedGenerate,
  };

  /** Write fileapi replies to disk.  */
  void WriteReplies(IndexFor indexFor);

  /** Get the "cmake" instance with which this was constructed.  */
  cmake* GetCMakeInstance() const { return this->CMakeInstance; }

  /** Convert a JSON object or array into an object with a single
      "jsonFile" member specifying a file named with the given prefix
      and holding the original object.  Other JSON types are unchanged.  */
  Json::Value MaybeJsonFile(Json::Value in, std::string const& prefix);

  /** Report file-api capabilities for cmake -E capabilities.  */
  static Json::Value ReportCapabilities();

  // Keep in sync with ObjectKindName.
  enum class ObjectKind
  {
    CodeModel,
    ConfigureLog,
    Cache,
    CMakeFiles,
    Toolchains,
    InternalTest
  };

  bool AddProjectQuery(ObjectKind kind, unsigned majorVersion,
                       unsigned minorVersion);

private:
  cmake* CMakeInstance;

  /** The api/v1 directory location.  */
  std::string APIv1;

  /** api/v1 directory in the user's shared CMake config directory.  */
  std::string UserAPIv1;

  /** The set of files we have just written to the reply directory.  */
  std::unordered_set<std::string> ReplyFiles;

  static std::vector<std::string> LoadDir(std::string const& dir);
  void RemoveOldReplyFiles();

  /** Identify one object kind and major version.  */
  struct Object
  {
    ObjectKind Kind;
    unsigned long Version = 0;
    friend bool operator<(Object const& l, Object const& r)
    {
      if (l.Kind != r.Kind) {
        return l.Kind < r.Kind;
      }
      return l.Version < r.Version;
    }
    friend bool operator==(Object const& l, Object const& r)
    {
      return l.Kind == r.Kind && l.Version == r.Version;
    }
    friend bool operator!=(Object const& l, Object const& r)
    {
      return !(l == r);
    }
  };

  /** Represent content of a query directory.  */
  struct Query
  {
    /** Known object kind-version pairs.  */
    std::vector<Object> Known;
    /** Unknown object kind names.  */
    std::vector<std::string> Unknown;
  };

  /** Represent one request in a client 'query.json'.  */
  struct ClientRequest : public Object
  {
    /** Empty if request is valid, else the error string.  */
    std::string Error;
  };

  /** Represent the "requests" in a client 'query.json'.  */
  struct ClientRequests : public std::vector<ClientRequest>
  {
    /** Empty if requests field is valid, else the error string.  */
    std::string Error;
  };

  /** Represent the content of a client query.json file.  */
  struct ClientQueryJson
  {
    /** The error string if parsing failed, else empty.  */
    std::string Error;

    /** The 'query.json' object "client" member if it exists, else null.  */
    Json::Value ClientValue;

    /** The 'query.json' object "requests" member if it exists, else null.  */
    Json::Value RequestsValue;

    /** Requests extracted from 'query.json'.  */
    ClientRequests Requests;
  };

  /** Represent content of a client query directory.  */
  struct ClientQuery
  {
    /** The content of the client query directory except 'query.json'.  */
    Query DirQuery;

    /** True if 'query.json' exists.  */
    bool HaveQueryJson = false;

    /** The 'query.json' content.  */
    ClientQueryJson QueryJson;
  };

  /** Whether the top-level query directory exists at all.  */
  bool QueryExists = false;

  /** The content of the top-level query directory.  */
  Query TopQuery;

  /** The content of each "client-$client" query directory.  */
  std::map<std::string, ClientQuery> ClientQueries;

  /** Reply index object generated for object kind/version.
      This populates the "objects" field of the reply index.  */
  std::map<Object, Json::Value> ReplyIndexObjects;

  /** Identify the situation in which WriteReplies was called.  */
  IndexFor ReplyIndexFor = IndexFor::Success;

  std::unique_ptr<Json::CharReader> JsonReader;
  std::unique_ptr<Json::StreamWriter> JsonWriter;

  bool ReadJsonFile(std::string const& file, Json::Value& value,
                    std::string& error);

  std::string WriteJsonFile(
    Json::Value const& value, std::string const& prefix,
    std::string (*computeSuffix)(std::string const&) = ComputeSuffixHash);
  static std::string ComputeSuffixHash(std::string const&);
  static std::string ComputeSuffixTime(std::string const&);

  static bool ReadQuery(std::string const& query,
                        std::vector<Object>& objects);
  void ReadClient(std::string const& client);
  void ReadClientQuery(std::string const& client, ClientQueryJson& q);

  Json::Value BuildReplyIndex();
  Json::Value BuildCMake();
  Json::Value BuildReply(Query const& q);
  Json::Value BuildReplyEntry(Object const& object);
  static Json::Value BuildReplyError(std::string const& error);
  Json::Value const& AddReplyIndexObject(Object const& o);

  static char const* ObjectKindName(ObjectKind kind);
  static std::string ObjectName(Object const& o);

  static Json::Value BuildVersion(unsigned int major, unsigned int minor);

  Json::Value BuildObject(Object const& object);

  ClientRequests BuildClientRequests(Json::Value const& requests);
  ClientRequest BuildClientRequest(Json::Value const& request);
  Json::Value BuildClientReply(ClientQuery const& q);
  Json::Value BuildClientReplyResponses(ClientRequests const& requests);
  Json::Value BuildClientReplyResponse(ClientRequest const& request);

  struct RequestVersion
  {
    unsigned int Major = 0;
    unsigned int Minor = 0;
  };
  static bool ReadRequestVersions(Json::Value const& version,
                                  std::vector<RequestVersion>& versions,
                                  std::string& error);
  static bool ReadRequestVersion(Json::Value const& version, bool inArray,
                                 std::vector<RequestVersion>& result,
                                 std::string& error);
  static std::string NoSupportedVersion(
    std::vector<RequestVersion> const& versions);

  void BuildClientRequestCodeModel(
    ClientRequest& r, std::vector<RequestVersion> const& versions);
  Json::Value BuildCodeModel(Object const& object);

  void BuildClientRequestConfigureLog(
    ClientRequest& r, std::vector<RequestVersion> const& versions);
  Json::Value BuildConfigureLog(Object const& object);

  void BuildClientRequestCache(ClientRequest& r,
                               std::vector<RequestVersion> const& versions);
  Json::Value BuildCache(Object const& object);

  void BuildClientRequestCMakeFiles(
    ClientRequest& r, std::vector<RequestVersion> const& versions);
  Json::Value BuildCMakeFiles(Object const& object);

  void BuildClientRequestToolchains(
    ClientRequest& r, std::vector<RequestVersion> const& versions);
  Json::Value BuildToolchains(Object const& object);

  void BuildClientRequestInternalTest(
    ClientRequest& r, std::vector<RequestVersion> const& versions);
  Json::Value BuildInternalTest(Object const& object);
};
