#pragma once

#ifndef VIVID2D_VERTEXLIST_H
#define VIVID2D_VERTEXLIST_H

#include <vector>
#include <string>
#include <algorithm>
#include <stdexcept>
#include <numeric>
#include <unordered_set>
#include "Vertex.h"

namespace Vivid2D::util {

    /**
     * @brief 一个自包含的几何数据单元，用于管理顶点（vertices）
     * 以及定义它们之间拓扑结构（三角形）的索引（indices）。
     *
     * 对应 Java 类 VertexList。
     */
    class VIVID_2D_MYDLL_API VertexList {
    private:
        std::string name;
        std::vector<int> indices;

    public:
        std::vector<Vertex> vertices;

        /**
         * @brief 默认构造函数。
         */
        VertexList();

        /**
         * @brief 构造函数
         *
         * @param name 此列表的名称
         */
        explicit VertexList(const std::string& name);

        /**
         * @brief 构造函数
         *
         * @param name            此列表的名称
         * @param initialVertices 用于初始化列表的顶点集合
         * @param initialIndices  用于初始化列表的索引集合
         */
        VertexList(const std::string& name, const std::vector<Vertex>& initialVertices, const std::vector<int>& initialIndices);

        VertexList(const VertexList& other);
        VertexList& operator=(const VertexList& other);

        // --- 列表管理 ---

        /**
         * @brief 向列表末尾添加一个顶点。
         *
         * @param vertex 要添加的顶点
         */
        void add(const Vertex& vertex);

        /**
         * @brief 移除列表中的指定顶点，并安全地移除所有引用它的三角形，同时重映射所有后续索引。
         *
         * @param vertex 要移除的顶点
         * @return 如果成功移除则为 true
         */
        bool remove(const Vertex& vertex);

        /**
         * @brief 移除指定索引处的顶点，并安全地移除所有引用它的三角形，同时重映射所有后续索引。
         *
         * @param index 要移除的索引
         * @return 被移除的顶点
         */
        Vertex remove(int index);

        /**
         * @brief 获取指定索引处的顶点。
         */
        const Vertex& get(int index) const;

        /**
         * @brief 返回列表中的顶点数量。
         */
        size_t size() const { return vertices.size(); }

        /**
         * @brief 检查列表是否为空。
         */
        bool isEmpty() const { return vertices.empty(); }

        /**
         * @brief 清空列表中的所有顶点和索引。
         */
        void clear();

        /**
         * @brief 返回内部顶点列表的副本。
         *
         * @return 顶点的列表副本
         */
        std::vector<Vertex> getVertices() const;

        /**
         * @brief 根据标签过滤并返回顶点列表。
         *
         * @return 过滤后的顶点列表
         */
        std::vector<Vertex> getVertices(VertexTag tag) const;

        // --- Getter 和 Setter ---

        const std::string& getName() const { return name; }
        void setName(const std::string& name);

        /**
         * @brief 获取索引数组的副本。
         *
         * @return 索引数组的副本
         */
        std::vector<int> getIndices() const;

        /**
         * @brief 获取仅由至少包含一个指定标签（Tag）的顶点组成的三角形索引。
         *
         * @param tag 要筛选的顶点标签
         * @return 一个新的索引数组，包含符合条件的三角形的原始索引。
         */
        std::vector<int> getIndices(VertexTag tag) const;

        /**
         * @brief 设置索引数组。
         *
         * @param indices 新的索引数组
         */
        void setIndices(const std::vector<int>& indices);

        /**
         * @brief 替换指定索引处的顶点。
         */
        void set(int index, const Vertex& vertex);

        // --- C++ 特性：迭代器 和 Object 方法 ---

        // C++ 迭代器支持 (代替 Java 的 Iterable 接口)
        auto begin() { return vertices.begin(); }
        auto end() { return vertices.end(); }
        auto begin() const { return vertices.cbegin(); }
        auto end() const { return vertices.cend(); }


        /**
         * @brief 重载相等运算符 (对应 Java 中的 equals())
         */
        bool operator==(const VertexList& other) const;

        /**
         * @brief 重载不等运算符
         */
        bool operator!=(const VertexList& other) const { return !(*this == other); }

        /**
         * @brief 重载输出流运算符 (对应 Java 中的 toString())
         */
        friend std::ostream& operator<<(std::ostream& os, const VertexList& vertexList);
    };

} // namespace util

#endif // VIVID2D_VERTEXLIST_H