#pragma once
#include <vector>
#include "dvm.h"
#include "graph_calls.h"
#include "json.hpp"

class ParallelStats
{
public:
    ParallelStats()
    {
        RemoteCount = ShadowCount = ReductionCount = AcrossCount = 0;
    }
     
    int RemoteCount = 0;
    int ShadowCount = 0;
    int ReductionCount = 0;
    int AcrossCount = 0;
};

class PredictorStats
{
public:
    PredictorStats()
    {
        ParallelCount = RemoteCount = RedistributeCount = IntervalCount = 0;
        TotalScorePar = TotalScoreComm = TotalScoreDist = 0;
    }
     
    ParallelStats ParallelStat;
    int ParallelCount = 0;
    int RemoteCount = 0;
    int RedistributeCount = 0;
    int IntervalCount = 0;
    int TotalScoreComm = 0;
    int TotalScorePar = 0;
    int TotalScoreDist = 0;

    nlohmann::json toJson()
    {
        nlohmann::json stat;

        stat["ParallelCount"] = ParallelCount;
        stat["RemoteCount"] = RemoteCount;
        stat["RedistributeCount"] = RedistributeCount;
        stat["IntervalCount"] = IntervalCount;

        stat["PS_RemoteCount"] = ParallelStat.RemoteCount;
        stat["PS_ShadowCount"] = ParallelStat.ShadowCount;
        stat["PS_ReductionCount"] = ParallelStat.ReductionCount;
        stat["PS_AcrossCount"] = ParallelStat.AcrossCount;

        //TODO: need to improve
        //                    (summed.TotalScoreComm != 0 ? 1.0 / summed.TotalScoreComm : 0.0) + (double)summed.TotalScorePar * 1000 + (countOfDist == 0 ? -5000 : countOfDist);
        stat["TotalScore"] = -1 * (ParallelStat.RemoteCount + ParallelStat.ShadowCount + ParallelStat.ReductionCount + ParallelStat.AcrossCount);
        return stat;
    }
};

void processFileToPredict(SgFile *file, PredictorStats &predictorCounts);

void calculateStatsForPredictor(const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo, const std::map<std::string, std::map<int, Gcov_info>>& gCovInfo);
void parseDvmDirForPredictor(const std::map<std::tuple<int, std::string, std::string>, std::pair<DIST::Array*, DIST::ArrayAccessInfo*>>& declaredArrays, const std::map<std::string, CommonBlock*>& commonBlocks, const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo, const std::map<std::string, std::map<int, Gcov_info>>& gCovInfo);