#pragma once

#include <string>
#include <set>
#include <map>

#include "AstWrapper.h"
#include "graph_loops.h"
#include "../Distribution/DvmhDirective.h"

struct DvmDirective
{
    std::set<Symbol*> corners;
    std::vector<std::pair<std::pair<Symbol*, std::string>, std::vector<std::pair<int, int>>>> shadowRenew, across;
    std::map<std::pair<std::pair<std::string, std::string>, std::string>, Expression*> remoteAccess;

    std::map<std::string, std::set<Symbol*>> reduction;
    std::map<std::string, std::set<std::tuple<Symbol*, Symbol*, int>>> reductionLoc;
};

bool isSPF_NoInline(Statement *stPrev);

template<typename fillType>
void fillPrivatesFromComment(Statement *st, std::set<fillType> &privates, int type = -1);

template<typename fillType>
void fillReductionsFromComment(Statement *st, std::map<std::string, std::set<fillType>> &reduction, bool moduleNameAdd = false, int type = SPF_ANALYSIS_DIR);

template<typename fillType>
void fillReductionsFromComment(Statement *st, std::map<std::string, std::set<std::tuple<fillType, fillType, int>>> &reduction, bool moduleNameAdd = false, int type = SPF_ANALYSIS_DIR);

void fillParameterFromComment(Statement *st, std::vector<std::pair<Expression*, Expression*>> &assigns);

template<typename fillType>
void fillShadowAcrossFromComment(const int type, Statement *st, std::vector<std::pair<std::pair<fillType, std::string>, std::vector<std::pair<int, int>>>> &data);

template<typename fillType>
void fillShadowAcrossFromParallel(const int type, Statement *st, std::vector<std::pair<std::pair<fillType, std::string>, std::vector<std::pair<int, int>>>> &data, std::set<fillType> &corner);

template<typename fillType>
void fillRemoteFromComment(Statement *st, std::map<std::pair<fillType, std::string>, Expression*> &remote, bool isFull = false, int type = SPF_PARALLEL_DIR);

void fillAcrossInfoFromDirectives(const LoopGraph *loopInfo, std::vector<std::pair<std::pair<std::string, std::string>, std::vector<std::pair<int, int>>>> &acrossInfo);
void fillInfoFromDirectives(const LoopGraph *loopInfo, ParallelDirective *directive);
void fillInfoFromDirective(Statement* parallel_on, DvmDirective& directive);

void fillFissionPrivatesExpansionFromComment(Statement *stIn, std::vector<std::string> &vars);

template<typename fillType>
void fillShrinkFromComment(Statement *stIn, std::vector<std::pair<fillType, std::vector<int>>> &varDims);

template<typename fillType>
void fillCheckpointFromComment(Statement *stIn, std::map<int, Expression*> &clauses, std::set<fillType> &vars, std::set<fillType> &expt);

template<typename fillType>
void fillMergeArraysFromComment(Statement* stIn, std::pair<fillType, fillType>& toReplace);

int getCoverPropertyFromComment(Statement* stIn);
