#pragma once

#include <vector>
#include <string>
#include <memory>
#include <cstring>
#include "gumbo.h"
#include "node.h"

namespace cutysoup {

// Forward declarations
class Tree;
class Node;

/**
 * Lightning-fast walker with zero-allocation bulk processing
 * 
 * Strategy: Completely eliminate all overhead sources:
 * - No shared_ptr creation during search (only at end)
 * - No memory allocations during traversal
 * - Cache-friendly linear memory access
 * - Specialized tag enum comparisons
 * - Inlined attribute lookup
 */
class LightningWalker {
public:
    struct Config {
        size_t reserve_capacity;
        bool use_linear_scan;  // For small documents
        
        Config() : reserve_capacity(64), use_linear_scan(true) {}
    };
    
    explicit LightningWalker(const Config& config = Config());
    
    // Lightning-fast tag search (enum-based, zero allocation)
    std::vector<std::shared_ptr<Node>> find_by_tag_lightning(
        GumboNode* root,
        const Tree* tree,
        const std::string& tag_name
    );
    
    // Lightning-fast class search (optimized string matching)
    std::vector<std::shared_ptr<Node>> find_by_class_lightning(
        GumboNode* root,
        const Tree* tree,
        const std::string& class_name
    );
    
    // Lightning-fast ID search (early termination)
    std::shared_ptr<Node> find_by_id_lightning(
        GumboNode* root,
        const Tree* tree,
        const std::string& id
    );
    
    // Zero-allocation bulk element collection
    void collect_elements_by_tag(
        GumboNode* root,
        GumboTag target_tag,
        std::vector<GumboNode*>& results
    );
    
    void collect_elements_by_class(
        GumboNode* root,
        const char* class_name,
        size_t class_len,
        std::vector<GumboNode*>& results
    );
    
private:
    Config config_;
    
    // Zero-allocation tree traversal
    template<typename Predicate>
    void traverse_linear(GumboNode* root, Predicate pred);
    
    // Ultra-fast attribute lookup (no string creation)
    inline const char* get_attribute_value_fast(const GumboVector* attrs, const char* name);
    inline bool has_class_name_fast(const char* class_attr, const char* target, size_t target_len);
    
    // Node creation (only when needed)
    std::shared_ptr<Node> create_node(GumboNode* gumbo_node, const Tree* tree) const;
    
    // Convert GumboNode vector to Node vector in one batch
    std::vector<std::shared_ptr<Node>> create_nodes_batch(
        const std::vector<GumboNode*>& gumbo_nodes,
        const Tree* tree
    ) const;
};

// Template implementations

template<typename Predicate>
void LightningWalker::traverse_linear(GumboNode* root, Predicate pred) {
    if (!root) return;
    
    // Use iterative approach with pre-allocated stack
    std::vector<GumboNode*> stack;
    stack.reserve(128);  // Avoid reallocations
    stack.push_back(root);
    
    while (!stack.empty()) {
        GumboNode* current = stack.back();
        stack.pop_back();
        
        if (!current) continue;
        
        // Process current node
        pred(current);
        
        // Add children in reverse order for correct traversal order
        if (current->type == GUMBO_NODE_ELEMENT) {
            const GumboVector* children = &current->v.element.children;
            for (int i = static_cast<int>(children->length) - 1; i >= 0; --i) {
                stack.push_back(static_cast<GumboNode*>(children->data[i]));
            }
        }
    }
}

} // namespace cutysoup