#pragma once

struct RemoteRequest
{
    LoopGraph* position;
    int dimNum;
    REMOTE_TYPE value;
    int currLine;
    int maxDimSize;

    explicit RemoteRequest(LoopGraph* position, int dimNum, REMOTE_TYPE value, int currLine, int maxDimSize) :
        position(position), dimNum(dimNum), value(value), currLine(currLine), maxDimSize(maxDimSize)
    { }
};

std::map<std::string, ArrayRefExp*>
createRemoteInParallel(const std::pair<LoopGraph*, const ParallelDirective*> under_dvm_dir,
                       const DIST::Arrays<int> &allArrays,
                       const std::map<LoopGraph*, std::map<DIST::Array*, ArrayInfo*>> &loopInfo,
                       DIST::GraphCSR<int, double, attrType> &reducedG,
                       const DataDirective &data,
                       const std::vector<int> &currVar,
                       std::vector<Messages> &messages,
                       const uint64_t regionId, 
                       const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls, 
                       const std::map<std::string, FuncInfo*>& funcMap);

void addRemoteLink(const LoopGraph* loop, const std::map<std::string, FuncInfo*>& funcMap, ArrayRefExp* expr, std::map<std::string, ArrayRefExp*>& uniqRemotes,
                   const std::set<std::string>& remotesInParallel, std::set<ArrayRefExp*>& addedRemotes, const std::vector<std::string>& mapToLoop,
                   std::vector<Messages>& messages, const int line, bool bindToLoopDistribution = true);

ArrayRefExp* createRemoteLink(const LoopGraph* currLoop, const DIST::Array* forArray);

std::vector<RemoteRequest> 
     checkArrayRefInLoopForRemoteStatus(bool ifUnknownArrayAssignFound,
                                        int sumMatched,
                                        int numOfSubs,
                                        int maxMatched,
                                        int currLine,
                                        DIST::Array* currArray,
                                        std::vector<int>& wasFound,
                                        ArrayRefExp* arrayRef,
                                        std::map<LoopGraph*, std::map<DIST::Array*, ArrayInfo*>>& loopInfo,
                                        const std::vector<int>& matchedToDim,
                                        const std::map<int, LoopGraph*>& sortedLoopGraph,
                                        const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls,
                                        const ParallelRegion* region,
                                        const std::vector<LoopGraph*>& parentLoops);
