#pragma once
#include "Element.hpp"
#include "nlohmann/json.hpp"

using json = nlohmann::json;

class MeshEntityStats
{
public:
    int element_count;
    int node_count;

    std::map<ElementTypes, int> element_type_count;

    MeshEntityStats()
    {
        element_count = 0;
        node_count = 0;
    };

    json getJson() const
    {
        json stat_json;
        for (auto ec : element_type_count)
        {
            stat_json[Element::createElement(ec.first)->getElementStringType() + "s"] = ec.second;
        }
        stat_json["elements"] = element_count;
        stat_json["nodes"] = node_count;
        return stat_json;
    }

    MeshEntityStats operator + (const MeshEntityStats& obj) 
    {
        MeshEntityStats st;
        st.element_count = element_count + obj.element_count;
        st.node_count = node_count + obj.node_count;

        st.element_type_count = element_type_count;

        for (auto mp : obj.element_type_count)
        {
            if (element_type_count.find(mp.first) != element_type_count.end())
            {
                st.element_type_count[mp.first] = st.element_type_count[mp.first] + mp.second;
            }
            else
            {
                st.element_type_count[mp.first] = mp.second;
            }
        }

        return st;
    }

    MeshEntityStats& MeshEntityStats::operator= (const MeshEntityStats& obj)
    {
        this->element_count = obj.element_count;
        this->node_count = obj.element_count;
        for (auto mp : obj.element_type_count)
        {
            this->element_type_count[mp.first] = mp.second;
        }
        return *this;
    }


};


class MeshStats
{
public:
    MeshEntityStats total_stats;
    std::map<std::string, MeshEntityStats> entity_stats;

    bool hasEntity(std::string n) const
    {
        return entity_stats.find(n) != entity_stats.end();
    }

};