#pragma once

#include "loop_analyzer.h"

#include <string>
#include <vector>
#include <map>
#include <set>
#include <tuple>
#include <stack>

#include "../Utils/leak_detector.h"

#if _WIN32 && NDEBUG && __BOOST
#include <boost/thread.hpp>
#endif
extern int passDone;

#include "../Distribution/Distribution.h"
#include "../Distribution/GraphCSR.h"
#include "../Distribution/Arrays.h"
#include "../ParallelizationRegions/ParRegions.h"

#include "../Utils/errors.h"
#include "../DirectiveProcessing/directive_parser.h"
#include "../DirectiveProcessing/directive_creator.h"

#include "../Utils/SgUtils.h"
#include "../Utils/AstWrapper.h"

#include "../GraphCall/graph_calls_func.h"
#include "../GraphLoop/graph_loops_func.h"
#include "../ParallelizationRegions/ParRegions_func.h"
#include "../DynamicAnalysis/gCov_parser_func.h"

#include "../ExpressionTransform/expr_transform.h"
#include "../SageAnalysisTool/depInterfaceExt.h"

#include "../VisualizerCalls/get_information.h"
#include "../VisualizerCalls/SendMessage.h"

#include "../Transformations/enddo_loop_converter.h"
#include "../DirectiveProcessing/remote_access.h"

#define PRINT_ARRAY_ARCS  0
#define PRINT_LOOP_STRUCT 0
#define PRINT_PROF_INFO   0
#define DEB               0

extern REGIME currRegime;
extern std::vector<Messages>* currMessages;

extern int mpiProgram;
extern int ignoreIO;
extern int parallizeFreeLoops;

void changeLoopWeight(double& currentWeight, const std::map<int, LoopGraph*>& sortedLoopGraph, const int line, bool increase = true);

SgStatement* takeOutConditions(std::stack<SgExpression*>& conditions, std::stack<SgStatement*>& ifBlocks, SgStatement* st);

void findArrayRef(const std::vector<SgForStmt*>& parentLoops, SgExpression* currExp, const int lineNum, const int side,
                  std::map<SgForStmt*, std::map<SgSymbol*, ArrayInfo>>& loopInfo, const std::set<std::string>& privatesVars,
                  std::vector<std::set<std::string>>& privatesVarsForLoop, std::map<int, LoopGraph*>& sortedLoopGraph,
                  const std::map<std::string, std::vector<SgExpression*>>& commonBlocks,
                  const std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>>& declaredArrays,
                  bool wasDistributedArrayRef, std::map<std::string, std::pair<SgSymbol*, SgStatement*>>& notMappedDistributedArrays,
                  std::set<std::string>& mappedDistrbutedArrays, SgStatement* currentSt, const ParallelRegion* reg, const double currentW,
                  const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);

bool hasNonPureFunctions(SgExpression* ex, LoopGraph* loopRef, std::vector<Messages>& messagesForFile, const int line, const std::map<std::string, FuncInfo*>& funcByName);