package _VisualDVM.ProjectData.SapforData.Regions;
import Common.Database.Objects.DBObject;
import Common.Utils.IntegerPairJson;
import Common.Utils.Pair;
import Common.Utils.Utils_;
import _VisualDVM.Global;
import _VisualDVM.ProjectData.Files.DBProjectFile;
import _VisualDVM.ProjectData.SapforData.Arrays.AlignRule;
import _VisualDVM.ProjectData.SapforData.Arrays.ArrayLocation;
import _VisualDVM.ProjectData.SapforData.Arrays.ProjectArray;
import com.google.gson.annotations.Expose;

import java.math.BigInteger;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Vector;
public class ParallelRegion extends DBObject {
    //json
    @Expose
    public String packedRegionId;
    @Expose
    public String originalName;
    @Expose
    public List<ProjectArray> packedArrays;
    @Expose
    public List<FileRegionLinesJson> regionsLines;
    @Expose
    public Vector<AlignRule> alignRules;
    //----
    public Vector<String> rules;
    //--
    public BigInteger regionId;
    //name in program
    // file -> <start, end> lines
    public LinkedHashMap<String, List<IntegerPairJson>> lines; //+
    //ключ - адрес. меняем
    public LinkedHashMap<BigInteger, ProjectArray> arraysMap; //+
    //for directive creating
    public int maxdim = 0;
    public Vector<String> fragments; //+
    public int lines_count = 0;
    public int loops_count = 0;
    public int arrays_count = 0;
    public int fd_count = 0;
    public int fc_count = 0;
    public void genRules(LinkedHashMap<BigInteger, ProjectArray> Arrays) {
        rules.clear();
        int maxLen = 0;
        for (AlignRule a : alignRules)
            maxLen = Math.max(maxLen, a.GetLenString());
        LinkedHashMap<String, Vector<String>> toPrint = new LinkedHashMap<>();
        for (AlignRule a : alignRules) {
            if (Arrays.get(a.alignArray_address).getLocation() != ArrayLocation.parameter) {
                Pair<String, String> result = a.GenRule(maxLen);
                if (!toPrint.containsKey(result.getKey()))
                    toPrint.put(result.getKey(), new Vector<>());
                toPrint.get(result.getKey()).add(result.getValue());
            }
        }
        for (Vector<String> v : toPrint.values())
            for (String r : v)
                rules.add(r);
    }
    public void Init() {
        arraysMap = new LinkedHashMap<>();
        lines = new LinkedHashMap<>();
        fragments = new Vector<>();
        rules = new Vector<>();
        //--
        if (packedRegionId != null)
            regionId = new BigInteger(packedRegionId);
        maxdim = 0;
        for (ProjectArray array : packedArrays) {
            array.Init();//имена и адреса.
            arraysMap.put(array.address, array);
            if (array.isTemplFlag == 1) {
                maxdim = Math.max(maxdim, array.dimSize);
                Global.mainModule.getProject().templates.add(array);
                array.regIDs.add(regionId);
            } else if (array.isLoopArrayFlag != 1) arrays_count++;
        }
        //---
        for (AlignRule rule : alignRules) {
            rule.Init();
            rule.parent_region = this;
        }
        //---
        for (FileRegionLinesJson fr : regionsLines) {
            fr.file = Utils_.toW(fr.file);
            lines.put(fr.file, fr.lines);
            for (IntegerPairJson l : fr.lines) {
                fragments.add(fr.file + ": " + l.getKey() + "-" + l.getKey());
            }
        }
        //---
        //--------------------------------------------------------------
        lines_count = 0;
        loops_count = 0;
        fd_count = 0;
        fc_count = 0;
        for (String FKey : lines.keySet()) {
            for (IntegerPairJson L : lines.get(FKey)) {
                lines_count += (L.getValue() - L.getKey());
                DBProjectFile f = Global.mainModule.getProject().db.files.Data.get(FKey);

                loops_count += f.FragmentLoopCount(L.getKey(), L.getValue());
                fc_count += f.FragmentFunctionCallsCount(L.getKey(), L.getValue());
                fd_count += f.FragmentFunctionDeclsCount(L.getKey(), L.getValue());
            }
        }
        //---
        packedRegionId = null;
        packedArrays.clear();
        packedArrays = null;
        regionsLines.clear();
        regionsLines = null;
        //--
    }
    public boolean ArrayBelongsToRegion(long id) {
        return arraysMap.values().stream().anyMatch(array -> array.id == id);
    }
    public ProjectArray getArrayById(long id) {
        for (ProjectArray array : arraysMap.values()) {
            if (array.id == id) return array;
        }
        return null;
    }
    @Override
    public String toString() {
        return "Область распараллеливания: " + originalName;
    }
    @Override
    public Object getPK() {
        return regionId;
    }
    public void UpdateLoopsCount() {
        loops_count = 0;
        for (String FKey : lines.keySet()) {
            for (IntegerPairJson L : lines.get(FKey)) {
                DBProjectFile f = Global.mainModule.getProject().db.files.Data.get(FKey);
                loops_count += f.FragmentLoopCount(L.getKey(), L.getValue());
            }
        }
    }
    public void UpdateFunctionsCount() {
        fd_count = 0;
        fc_count = 0;
        for (String FKey : lines.keySet()) {
            for (IntegerPairJson L : lines.get(FKey)) {
                DBProjectFile f = Global.mainModule.getProject().db.files.Data.get(FKey);
                fc_count += f.FragmentFunctionCallsCount(L.getKey(), L.getValue());
                fd_count += f.FragmentFunctionDeclsCount(L.getKey(), L.getValue());
            }
        }
    }
    public void UpdateArraysCount() {
        arrays_count = 0;
        for (String FKey : lines.keySet()) {
            for (IntegerPairJson L : lines.get(FKey)) {
                DBProjectFile f = Global.mainModule.getProject().db.files.Data.get(FKey);
                arrays_count += f.FragmentArraysCount(L.getKey(), L.getValue());
            }
        }
    }
}
