#pragma once

#include <memory>
#include <vector>
#include <list> // For std::list
#include "lumacs/window.hpp" // For Window and LayoutNode
#include "lumacs/buffer.hpp" // For shared_ptr<Buffer>
#include "lumacs/i_window_manager.hpp"

namespace lumacs {

class EditorCore; // Forward declaration
class BufferManager; // Forward declaration
class IEditorNotifier;

/// @brief Manages the layout and interaction of editor windows.
class WindowManager : public IWindowManager {
public:
    WindowManager(IEditorNotifier& notifier, BufferManager& buffer_manager);

    /// @brief Get the currently active window.
    /// @return A shared pointer to the active window.
    [[nodiscard]] std::shared_ptr<Window> active_window() const override;

    /// @brief Set the currently active window.
    /// @param window A shared pointer to the window to make active.
    /// @return True if the window was set as active, false otherwise.
    bool set_active_window(std::shared_ptr<Window> window);

    /// @brief Splits the active window horizontally, creating a new window below it.
    void split_horizontally();

    /// @brief Splits the active window vertically, creating a new window to its right.
    void split_vertically();

    /// @brief Closes the active window. If it's the last window, it's not closed.
    void close_active_window();

    /// @brief Cycles focus to the next window in the layout.
    void next_window();

    /// @brief Get the root node of the window layout tree.
    [[nodiscard]] std::shared_ptr<LayoutNode> root_layout() const override { return root_node_; }

    /// @brief Helper to collect all windows in traversal order.
    /// @param node The current node to traverse.
    /// @param windows The vector to populate with windows.
    void collect_windows(LayoutNode* node, std::vector<std::shared_ptr<Window>>& windows) override;

private:
    IEditorNotifier& notifier_;
    BufferManager& buffer_manager_;

    std::shared_ptr<LayoutNode> root_node_;
    std::shared_ptr<Window> active_window_;

    // Helper functions for tree manipulation
    LayoutNode* find_parent_of_node(LayoutNode* current, LayoutNode* child_target);
    LayoutNode* find_node_with_window(LayoutNode* current, std::shared_ptr<Window> target);
    bool replace_window_node(std::shared_ptr<LayoutNode> node, 
                            std::shared_ptr<Window> target, 
                            std::shared_ptr<LayoutNode> replacement);
};

} // namespace lumacs