/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#ifndef cmXMLWiter_h
#define cmXMLWiter_h

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

#include "cmXMLSafe.h"

#include <chrono>
#include <ctime>
#include <ostream>
#include <stack>
#include <string>
#include <vector>

class cmXMLWriter
{
public:
  cmXMLWriter(std::ostream& output, std::size_t level = 0);
  ~cmXMLWriter();

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

  void StartDocument(const char* encoding = "UTF-8");
  void EndDocument();

  void StartElement(std::string const& name);
  void EndElement();

  void BreakAttributes();

  template <typename T>
  void Attribute(const char* name, T const& value)
  {
    this->PreAttribute();
    this->Output << name << "=\"" << SafeAttribute(value) << '"';
  }

  void Element(const char* name);

  template <typename T>
  void Element(std::string const& name, T const& value)
  {
    this->StartElement(name);
    this->Content(value);
    this->EndElement();
  }

  template <typename T>
  void Content(T const& content)
  {
    this->PreContent();
    this->Output << SafeContent(content);
  }

  void Comment(const char* comment);

  void CData(std::string const& data);

  void Doctype(const char* doctype);

  void ProcessingInstruction(const char* target, const char* data);

  void FragmentFile(const char* fname);

  void SetIndentationElement(std::string const& element);

private:
  void ConditionalLineBreak(bool condition);

  void PreAttribute();
  void PreContent();

  void CloseStartElement();

private:
  static cmXMLSafe SafeAttribute(const char* value)
  {
    return cmXMLSafe(value);
  }

  static cmXMLSafe SafeAttribute(std::string const& value)
  {
    return cmXMLSafe(value);
  }

  template <typename T>
  static T SafeAttribute(T value)
  {
    return value;
  }

  static cmXMLSafe SafeContent(const char* value)
  {
    return cmXMLSafe(value).Quotes(false);
  }

  static cmXMLSafe SafeContent(std::string const& value)
  {
    return cmXMLSafe(value).Quotes(false);
  }

  /*
   * Convert a std::chrono::system::time_point to the number of seconds since
   * the UN*X epoch.
   *
   * It would be tempting to convert a time_point to number of seconds by
   * using time_since_epoch(). Unfortunately the C++11 standard does not
   * specify what the epoch of the system_clock must be.
   * Therefore we must assume it is an arbitrary point in time. Instead of this
   * method, it is recommended to convert it by means of the to_time_t method.
   */
  static std::time_t SafeContent(
    std::chrono::system_clock::time_point const& value)
  {
    return std::chrono::system_clock::to_time_t(value);
  }

  template <typename T>
  static T SafeContent(T value)
  {
    return value;
  }

private:
  std::ostream& Output;
  std::stack<std::string, std::vector<std::string>> Elements;
  std::string IndentationElement;
  std::size_t Level;
  std::size_t Indent;
  bool ElementOpen;
  bool BreakAttrib;
  bool IsContent;
};

class cmXMLElement; // IWYU pragma: keep

class cmXMLDocument
{
public:
  cmXMLDocument(cmXMLWriter& xml)
    : xmlwr(xml)
  {
    xmlwr.StartDocument();
  }
  ~cmXMLDocument() { xmlwr.EndDocument(); }
  cmXMLDocument(const cmXMLDocument&) = delete;
  cmXMLDocument& operator=(const cmXMLDocument&) = delete;

private:
  friend class cmXMLElement;
  cmXMLWriter& xmlwr;
};

class cmXMLElement
{
public:
  cmXMLElement(cmXMLWriter& xml, const char* tag)
    : xmlwr(xml)
  {
    xmlwr.StartElement(tag);
  }
  cmXMLElement(cmXMLElement& par, const char* tag)
    : xmlwr(par.xmlwr)
  {
    xmlwr.StartElement(tag);
  }
  cmXMLElement(cmXMLDocument& doc, const char* tag)
    : xmlwr(doc.xmlwr)
  {
    xmlwr.StartElement(tag);
  }
  ~cmXMLElement() { xmlwr.EndElement(); }

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

  template <typename T>
  cmXMLElement& Attribute(const char* name, T const& value)
  {
    xmlwr.Attribute(name, value);
    return *this;
  }
  template <typename T>
  void Content(T const& content)
  {
    xmlwr.Content(content);
  }
  template <typename T>
  void Element(std::string const& name, T const& value)
  {
    xmlwr.Element(name, value);
  }
  void Comment(const char* comment) { xmlwr.Comment(comment); }

private:
  cmXMLWriter& xmlwr;
};

#endif
