#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <rapidjson/document.h>
#include <rapidjson/filereadstream.h>

using namespace std;
using namespace rapidjson;

class FSMBase {
public:
    string StateName;
    string EventName;
    std::vector<FSMBase*> subitem;

public:
    FSMBase() {
        std::cout << "default constructor called" << std::endl;
    }

    virtual void getdata() {
        std::cout << "FSMBase called" << std::endl;
    }

    virtual void Add(FSMBase* b1) {
        subitem.push_back(b1);
        b1->getdata();
    }

    virtual ~FSMBase() {
        std::cout << "destructor called" << std::endl;
        for (auto item : subitem) {
            delete item; // Clean up dynamically allocated memory
        }
    }
};

class PrimitiveTool : public FSMBase {
public:
    void Add(FSMBase* b1) override {
        subitem.push_back(b1);
        b1->getdata();
    }
};

class Event : public FSMBase {
    string ActionType;
    string ActionParam;

public:
    void getdata(string Name, string ActType, string ActPar) {
        EventName = Name;
        ActionType = ActType;
        ActionParam = ActPar;
        std::cout << "Event: " << EventName << ", ActionType: " << ActionType << ", ActionParam: " << ActionParam << std::endl;
    }
};

class State : public FSMBase {
    string EntryMethodName;
    std::vector<Event*> eventitem;

public:
    void getdata(string Name, string Methodname) {
        StateName = Name;
        EntryMethodName = Methodname;
        std::cout << "State: " << StateName << ", EntryMethodName: " << EntryMethodName << std::endl;
    }

    void Add(FSMBase* fsmbase1) override {
        subitem.push_back(fsmbase1);
        fsmbase1->getdata();
    }
};

void createFSMFromJSON(const char* filename) {
    // Open the file
    ifstream file(filename);
    if (!file.is_open()) {
        cerr << "Could not open file: " << filename << endl;
        return;
    }

    // Read the entire file into a string
    string json((istreambuf_iterator<char>(file)), istreambuf_iterator<char>());
    
    Document doc;
    
    // Parse the JSON data
    doc.Parse(json.c_str());

    // Check for parse errors
    if (doc.HasParseError()) {
        cerr << "Error parsing JSON: " << doc.GetParseError() << endl;
        return;
    }

    // Create a PrimitiveTool object
    PrimitiveTool* primitiveTool = new PrimitiveTool();

    // Iterate through states in the JSON
    const Value& states = doc["PrimitiveTool"]["State"];
    
    for (SizeType i = 0; i < states.Size(); i++) {
        const Value& stateValue = states[i];
        
        if (stateValue.HasMember("Name") && stateValue["Name"].IsString() &&
            stateValue.HasMember("EntryMethodName") && stateValue["EntryMethodName"].IsString()) {

            State* state = new State();
            state->getdata(stateValue["Name"].GetString(), stateValue["EntryMethodName"].GetString());

            // Process events if they exist
            if (stateValue.HasMember("Event")) {
                const Value& events = stateValue["Event"];
                if (events.IsArray()) {
                    for (SizeType j = 0; j < events.Size(); j++) {
                        const Value& eventValue = events[j];
                        if (eventValue.HasMember("Name") && eventValue["Name"].IsString() &&
                            eventValue.HasMember("ActionType") && eventValue["ActionType"].IsString() &&
                            eventValue.HasMember("ActionParam") && eventValue["ActionParam"].IsString()) {

                            Event* event = new Event();
                            event->getdata(eventValue["Name"].GetString(),
                                           eventValue["ActionType"].GetString(),
                                           eventValue["ActionParam"].GetString());
                            state->Add(event);
                        }
                    }
                }
            }

            primitiveTool->Add(state);
        }
    }

    // Clean up
    delete primitiveTool;

}

int main() {
    createFSMFromJSON("FsmImplementation.json");
    
    return 0;
}

modify the code such that it follows single responsibility principle