// Copyright 2015 The Weave 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 LIBWEAVE_SRC_NOTIFICATION_XMPP_STREAM_PARSER_H_
#define LIBWEAVE_SRC_NOTIFICATION_XMPP_STREAM_PARSER_H_

#include <expat.h>

#include <map>
#include <memory>
#include <stack>
#include <string>

#include <base/macros.h>

namespace weave {

class XmlNode;

// A simple XML stream parser. As the XML data is being read from a data source
// (for example, a socket), XmppStreamParser::ParseData() should be called.
// This method parses the provided XML data chunk and if it finds complete
// XML elements, it will call internal OnOpenElement(), OnCloseElement() and
// OnCharData() member functions. These will track the element nesting level.
// When a top-level element starts, the parser will call Delegate::OnStreamStart
// method. Once this happens, every complete XML element (including its children
// if they are present) will trigger Delegate::OnStanze() callback.
// Finally, when top-level element is closed, Delegate::OnStreamEnd() is called.
// This class is specifically tailored to XMPP streams which look like this:
// B:  <stream:stream to='example.com' xmlns='jabber:client' version='1.0'>
// S:    <presence><show/></presence>
// S:    <message to='foo'><body/></message>
// S:    <iq to='bar'><query/></iq>
// S:    ...
// E:  </stream:stream>
// Here, "B:" will trigger OnStreamStart(), "S:" will result in OnStanza() and
// "E:" will result in OnStreamEnd().
class XmppStreamParser final {
 public:
  // Delegate interface that interested parties implement to receive
  // notifications of stream opening/closing and on new stanzas arriving.
  class Delegate {
   public:
    virtual void OnStreamStart(
        const std::string& node_name,
        std::map<std::string, std::string> attributes) = 0;
    virtual void OnStreamEnd(const std::string& node_name) = 0;
    virtual void OnStanza(std::unique_ptr<XmlNode> stanza) = 0;

   protected:
    virtual ~Delegate() = default;
  };

  explicit XmppStreamParser(Delegate* delegate);
  ~XmppStreamParser();

  // Parses additional XML data received from an input stream.
  void ParseData(const std::string& data);

  // Resets the parser to expect the top-level stream node again.
  void Reset();

 private:
  // Raw expat callbacks.
  static void HandleElementStart(void* user_data,
                                 const XML_Char* element,
                                 const XML_Char** attr);
  static void HandleElementEnd(void* user_data, const XML_Char* element);
  static void HandleCharData(void* user_data, const char* content, int length);

  // Reinterpreted callbacks from expat with some data pre-processed.
  void OnOpenElement(const std::string& node_name,
                     std::map<std::string, std::string> attributes);
  void OnCloseElement(const std::string& node_name);
  void OnCharData(const std::string& text);

  Delegate* delegate_;
  XML_Parser parser_{nullptr};
  bool started_{false};
  std::stack<std::unique_ptr<XmlNode>> node_stack_;

  DISALLOW_COPY_AND_ASSIGN(XmppStreamParser);
};

}  // namespace weave

#endif  // LIBWEAVE_SRC_NOTIFICATION_XMPP_STREAM_PARSER_H_
