/*
 * Author:          Patrick-Christopher Mattulat
 * Co-Author:       Claude Sonnet 4.6 (LLM)
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2020-11-25
 * Changed:         2026-06-23
 *
 * */

#ifndef LS_STD_XML_PARSER_HPP
#define LS_STD_XML_PARSER_HPP

#include "XmlDocument.hpp"
#include "XmlParseMode.hpp"
#include "XmlParseParameter.hpp"
#include <list>
#include <ls-std/core/Class.hpp>
#include <ls-std/core/type/Types.hpp>
#include <ls-std/os/dynamic-goal.hpp>
#include <string_view>

/*
 * @doc: class(name: 'XmlParser', package: 'io')
 * @doc: io.XmlParser.description('This class parses a whole XML tree in form of an XML document.')
 * */

namespace ls::standard::io
{
  class LS_STD_DYNAMIC_GOAL XmlParser : public ls::standard::core::Class
  {
    public:

      explicit XmlParser(const ::std::shared_ptr<ls::standard::io::XmlDocument> &_document);
      ~XmlParser() noexcept override;

      [[nodiscard]] ::std::shared_ptr<ls::standard::io::XmlDocument> getDocument() const;
      void parse(const ls::standard::core::type::byte_field &_data);
      void setDocument(const ::std::shared_ptr<ls::standard::io::XmlDocument> &_document);

    protected:

      [[nodiscard]] static ::std::pair<::std::string, ::std::string> _readAttribute_(const ls::standard::core::type::byte_field &_data);
      [[nodiscard]] static ::std::list<::std::pair<::std::string, ::std::string>> _readAttributes_(ls::standard::core::type::byte_field _data);

    private:

      uint8_t currentLevel{};
      ::std::shared_ptr<ls::standard::io::XmlDocument> document{};
      uint8_t maxLevel{};
      ls::standard::io::XmlParseMode mode{};
      ::std::list<ls::standard::io::XmlParseParameter> parseParameters{};

      void _analyze(const ls::standard::core::type::byte_field &_data, ::std::string::size_type _index);
      void _assignDocument(const ::std::shared_ptr<ls::standard::io::XmlDocument> &_document);
      [[nodiscard]] static bool _contains(::std::string_view _text, ::std::string_view _searchText);
      [[nodiscard]] static ::std::shared_ptr<ls::standard::io::XmlDeclaration> _createDeclaration(const ::std::list<::std::pair<::std::string, ::std::string>> &_attributes);
      [[nodiscard]] static ::std::shared_ptr<ls::standard::io::XmlNode> _createNode(const ::std::list<::std::pair<::std::string, ::std::string>> &_attributes, ::std::string_view _name);
      [[nodiscard]] static bool _endsWith(::std::string_view _text, ::std::string_view _ending);
      [[nodiscard]] static ::std::pair<::std::string, ::std::string> _findAttribute(const ::std::list<::std::pair<::std::string, ::std::string>> &_attributes, const ::std::string &_name);
      [[nodiscard]] static size_t _findAttributeEndPosition(const ls::standard::core::type::byte_field &_data);
      [[nodiscard]] static ls::standard::core::type::byte_field _getNextTagString(::std::string_view _data, ::std::string::size_type _index);
      void _isClosingTag(::std::string_view _data, ::std::string::size_type _index);
      void _isDeclaration(::std::string_view _data, ::std::string::size_type _index);
      void _isOpeningTag(::std::string_view _data, ::std::string::size_type _index);
      void _isValue(const ls::standard::core::type::byte_field &_data, ::std::string::size_type _index);
      void _mergeNodes();
      void _mergeChildrenToParentNode(const ::std::shared_ptr<ls::standard::io::XmlNode> &_parent, ::std::list<ls::standard::io::XmlParseParameter>::iterator &_iterator, uint8_t _parentLevel);
      void _mergeNodesOnCurrentLevel();
      void _parse(const ls::standard::core::type::byte_field &_data);
      [[nodiscard]] static ::std::pair<::std::string, ::std::string> _parseAttribute(::std::string_view _data);
      [[nodiscard]] static ::std::list<::std::pair<::std::string, ::std::string>> _parseAttributes(ls::standard::core::type::byte_field _data);
      [[nodiscard]] size_t _parseClosingTag(const ls::standard::core::type::byte_field &_data, ::std::string::size_type _index);
      [[nodiscard]] size_t _parseDeclaration(const ls::standard::core::type::byte_field &_data, ::std::string::size_type _index) const;
      [[nodiscard]] ::std::string::size_type _parseMode(::std::string::size_type _index, const ls::standard::core::type::byte_field &_data);
      [[nodiscard]] size_t _parseOpeningTag(const ls::standard::core::type::byte_field &_data, ::std::string::size_type _index);
      [[nodiscard]] static ::std::string_view _parseTagName(::std::string_view _data);
      [[nodiscard]] size_t _parseValue(::std::string_view _data, ::std::string::size_type _index) const;
      void _reset();
      void _setMaxLevel();
  };
}

#endif
