package _VisualDVM.ProjectData.SapforData.Regions;
import Common.Utils.Utils_;
import _VisualDVM.Current;
import Common.Database.Objects.DBObject;
import Common.Utils.Index;
import _VisualDVM.Global;
import _VisualDVM.ProjectData.Files.DBProjectFile;
import _VisualDVM.ProjectData.SapforData.Arrays.Distribution.AlignRule;
import _VisualDVM.ProjectData.SapforData.Arrays.Distribution.DataDirective;
import _VisualDVM.ProjectData.SapforData.Arrays.ProjectArray;
import javafx.util.Pair;

import java.math.BigInteger;
import java.util.LinkedHashMap;
import java.util.Vector;
public class ParallelRegion extends DBObject {
    public BigInteger regionId;
    //name in program
    public String originalName;
    // file -> <start, end> lines
    public LinkedHashMap<String, Vector<Pair<Integer, Integer>>> lines;
    //ключ - адрес. меняем
    public LinkedHashMap<BigInteger, ProjectArray> arrays;
    //for directive creating
    public DataDirective dataDirectives;
    public int maxdim = 0;
    public Vector<String> fragments = new Vector<>();
    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 ParallelRegion(String[] splited, Index idx) {
        // regionId = Long.parseLong(splited[idx.Inc()]);
        regionId = new BigInteger(splited[idx.Inc()]);
        originalName = splited[idx.Inc()];
        String[] localSplited = splited[idx.Inc()].split("\\|");
        int lines_size = Integer.parseInt(localSplited[0]);
        lines = new LinkedHashMap<>(lines_size);
        //распаковка Lines -----------------------------------------------
        //---------------------------------------------------------------
        for (int i = 0; i < lines_size; ++i) {
            String line_file = Utils_.toW(localSplited[1]);
            int line_list_size = Integer.parseInt(localSplited[2]);
            Vector<Pair<Integer, Integer>> current_lines = new Vector<>(line_list_size);
            for (int k = 0; k < line_list_size; ++k) {
                int first = Integer.parseInt(splited[idx.Inc()]);
                if (first == 0) first++;
                localSplited = splited[idx.Inc()].split("\\|");
                int second = Integer.parseInt((localSplited[0]));
                current_lines.add(new Pair<>(first, second));
                fragments.add(line_file + ": " + first + "-" + second);
            }
            lines.put(line_file, current_lines);
        }
        maxdim = 0;
        int arrays_size = Integer.parseInt(splited[idx.Inc()]);
        arrays = new LinkedHashMap<>(arrays_size);
        for (int i = 0; i < arrays_size; ++i) {
            //long array_address = Long.parseLong((splited[idx.Inc()]));
            BigInteger array_address = new BigInteger((splited[idx.Inc()]));
            ProjectArray new_array = new ProjectArray(splited, idx, array_address);
            arrays.put(array_address, new_array);
            //-------------------------------------------------------
            if (new_array.isTemplFlag == 1) {
                maxdim = Math.max(maxdim, new_array.dimSize);
                Global.mainModule.getProject().templates.add(new_array);
                new_array.regIDs.add(regionId);
            } else if (new_array.isLoopArrayFlag != 1) arrays_count++;
        }
        int dataDirectives_alignRules_size = Integer.parseInt(splited[idx.Inc()]);
        dataDirectives = new DataDirective();
        dataDirectives.alignRules = new Vector<>(dataDirectives_alignRules_size);
        for (int i = 0; i < dataDirectives_alignRules_size; ++i)
            dataDirectives.alignRules.add(new AlignRule(splited, idx));
        for (int i = 0; i < dataDirectives.alignRules.size(); ++i)
            dataDirectives.alignRules.get(i).parent_region = this;
        //--------------------------------------------------------------
        lines_count = 0;
        loops_count = 0;
        fd_count = 0;
        fc_count = 0;
        for (String FKey : lines.keySet()) {
            for (Pair<Integer, Integer> 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());
            }
        }
        //--------------------------------------------------
    }
    public boolean ArrayBelongsToRegion(long id) {
        return arrays.values().stream().anyMatch(array -> array.id == id);
    }
    public ProjectArray getArrayById(long id) {
        for (ProjectArray array : arrays.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 (Pair<Integer, Integer> 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 (Pair<Integer, Integer> 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 (Pair<Integer, Integer> L : lines.get(FKey)) {
                DBProjectFile f = Global.mainModule.getProject().db.files.Data.get(FKey);
                arrays_count += f.FragmentArraysCount(L.getKey(), L.getValue());
            }
        }
        /*
        if (new_array.isTemplFlag == 1) {
            maxdim = Math.max(maxdim, new_array.dimSize);
            Current.getProject().templates.put(new_array.address, new_array);
            new_array.regIDs.add(regionId);
        } else if (new_array.isLoopArrayFlag != 1) arrays_count++;
         */
    }
}
