#pragma once
#include <vector>
#include <stdexcept>

/**
 * @brief 链表节点模板类
 * @tparam T 节点存储的数据类型
 * 
 * 技术点: 模板 (Template)
 */
template <typename T>
struct Node {
    T data;
    Node<T>* next;
    
    explicit Node(const T& d) : data(d), next(nullptr) {}
};

/**
 * @brief 历史日志记录器 - 使用模板和手写链表实现
 * @tparam T 日志条目的数据类型
 * 
 * 技术点: 
 * 1. 模板 (Template) - 泛型编程
 * 2. 链表 (Linked List) - 手写数据结构
 * 
 * 用途: 用于记录战斗日志，满足课程要求的"模板+链表"技术点
 */
template <typename T>
class HistoryLog {
private:
    Node<T>* head;    // 链表头指针
    Node<T>* tail;    // 链表尾指针 (用于快速追加)
    int size;         // 链表大小

public:
    /**
     * @brief 构造函数
     */
    HistoryLog() : head(nullptr), tail(nullptr), size(0) {}

    /**
     * @brief 析构函数 - 必须正确释放所有节点内存
     */
    ~HistoryLog() {
        clear();
    }

    /**
     * @brief 拷贝构造函数 (深拷贝)
     */
    HistoryLog(const HistoryLog& other) : head(nullptr), tail(nullptr), size(0) {
        Node<T>* current = other.head;
        while (current != nullptr) {
            add(current->data);
            current = current->next;
        }
    }

    /**
     * @brief 拷贝赋值运算符
     */
    HistoryLog& operator=(const HistoryLog& other) {
        if (this != &other) {
            clear();
            Node<T>* current = other.head;
            while (current != nullptr) {
                add(current->data);
                current = current->next;
            }
        }
        return *this;
    }

    /**
     * @brief 在链表尾部添加新的日志条目
     * @param logEntry 日志条目
     */
    void add(const T& logEntry) {
        Node<T>* newNode = new Node<T>(logEntry);
        
        if (head == nullptr) {
            // 空链表
            head = newNode;
            tail = newNode;
        } else {
            // 追加到尾部
            tail->next = newNode;
            tail = newNode;
        }
        
        size++;
    }

    /**
     * @brief 在链表头部插入日志条目
     * @param logEntry 日志条目
     */
    void addFront(const T& logEntry) {
        Node<T>* newNode = new Node<T>(logEntry);
        
        if (head == nullptr) {
            head = newNode;
            tail = newNode;
        } else {
            newNode->next = head;
            head = newNode;
        }
        
        size++;
    }

    /**
     * @brief 获取所有日志条目
     * @return std::vector<T> 包含所有日志条目的向量
     */
    std::vector<T> getAllEntries() const {
        std::vector<T> entries;
        entries.reserve(size);
        
        Node<T>* current = head;
        while (current != nullptr) {
            entries.push_back(current->data);
            current = current->next;
        }
        
        return entries;
    }

    /**
     * @brief 获取链表大小
     * @return int 日志条目数量
     */
    int getSize() const {
        return size;
    }

    /**
     * @brief 检查链表是否为空
     * @return bool true 如果为空
     */
    bool isEmpty() const {
        return size == 0;
    }

    /**
     * @brief 清空所有日志条目
     */
    void clear() {
        Node<T>* current = head;
        while (current != nullptr) {
            Node<T>* temp = current;
            current = current->next;
            delete temp;
        }
        head = nullptr;
        tail = nullptr;
        size = 0;
    }

    /**
     * @brief 获取指定索引的日志条目
     * @param index 索引 (0-based)
     * @return const T& 日志条目的引用
     * @throw std::out_of_range 如果索引超出范围
     */
    const T& at(int index) const {
        if (index < 0 || index >= size) {
            throw std::out_of_range("Index out of range");
        }
        
        Node<T>* current = head;
        for (int i = 0; i < index; i++) {
            current = current->next;
        }
        
        return current->data;
    }

    /**
     * @brief 打印所有日志 (仅用于调试)
     */
    void print() const {
        Node<T>* current = head;
        int index = 0;
        while (current != nullptr) {
            // 这里假设 T 支持 << 运算符
            // std::cout << "[" << index++ << "] " << current->data << std::endl;
            current = current->next;
            index++;
        }
    }
};
