#pragma once

#include <unordered_map>

#include "SgUtils.h"
#include "CommonBlock.h"
#include "graph_calls.h"

#include "CFGraph.h"
#include "IR.h"

inline bool hasStoreStructure(SAPFOR::CFG_OP type)
{
    return (type == SAPFOR::CFG_OP::STORE) ||
        (type == SAPFOR::CFG_OP::REC_REF_STORE) ||
        (type == SAPFOR::CFG_OP::POINTER_ASS);
}

const std::map<std::string, SgSymbol*>& getCommonArgsByFunc(FuncInfo* func, std::map<FuncInfo*, std::map<std::string, SgSymbol*>>& cache,
                                                            const std::vector<std::pair<const Variable*, CommonBlock*>>& commonVars,
                                                            std::unordered_map<SgSymbol*, std::string>& globals_cache,
                                                            std::unordered_map<SgSymbol*, std::string>& locals_cache);

std::vector<SAPFOR::BasicBlock*> sortCfgNodes(const std::vector<SAPFOR::BasicBlock*>& blocks,
                                              std::set<std::pair<SAPFOR::BasicBlock*, SAPFOR::BasicBlock*>>* ignored_edges = NULL);

const std::string& getArgNameBySymbol(const std::vector<std::pair<const Variable*, CommonBlock*>>& commonVars,
                                      const FuncInfo* func, SgSymbol* s, std::unordered_map<SgSymbol*, std::string>& globals_cache, 
                                      std::unordered_map<SgSymbol*, std::string>& locals_cache);

// main functions of SUBST_EXPR_RD pass
void buildSubstitutions(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph_for_project, const std::map<std::string, CommonBlock*>& commonBlocks, SgProject* project);
void performRDSubst(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph_for_project, const std::map<std::string, CommonBlock*>& commonBlocks, SgProject* project);
void revertSubstitutions();

void cancelRevertionForStatement(std::string filename, SgStatement* stmt, int i);

/*void destroyReplacementsInFiles();
void destroyOldExpressionsInFile();
void destroyAllSubstitutionsData();*/