package algorithms.convexhullvg;


import java.awt.Color;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;

import algorithms.rotationalplanesweep.ConvexHullRPSScanner;
import grid.GridGraph;

import algorithms.datatypes.SnapshotItem;

public class ConvexHullVG {

    private Runnable snapshotAction;

    private final GridGraph graph;
    private final int sizeXPlusOne;
    private final int sizeYPlusOne;
    private ConvexHullRPSScanner scanner;

    private final int[] nodeIndex; // Flattened 2D Array
    private int[] nodeX;
    private int[] nodeY;

    private ConvexHull[] convexHulls;
    private int nNodes;
    
    public static class ConvexHull {
        public int[] xVertices;
        public int[] yVertices;
        public int size;
    }
    
    public ConvexHullVG(GridGraph graph) {
        this.graph = graph;
        this.sizeXPlusOne = graph.sizeX+1;
        this.sizeYPlusOne = graph.sizeY+1;
        nodeIndex = new int[sizeYPlusOne*sizeXPlusOne];
    }

    public final void setSnapshotAction(Runnable action) {
        snapshotAction = action;
    }

    public void initialise(int sx, int sy, int ex, int ey) {
        initialiseConvexHulls();
        if (snapshotAction != null) snapshotAction.run();
        initialiseNodes();
        scanner = new ConvexHullRPSScanner(graph, convexHulls, convexHulls.length);
    }
    
    private void initialiseConvexHulls() {
        convexHulls = ConvexHullSplitGenerator.generate(graph);
    }

    private void initialiseNodes() {
        int nNodes = 0;
        for (int i=0; i<convexHulls.length; ++i) {
            ConvexHull hull = convexHulls[i];
            for (int j=0; j<hull.size; ++j) {
                int x = hull.xVertices[j];
                int y = hull.yVertices[j];

                nodeIndex[y*sizeXPlusOne + x] = nNodes;
                ++nNodes;
            }
        }

        nodeX = new int[nNodes];
        nodeY = new int[nNodes];
        int index = 0;
        for (int i=0; i<convexHulls.length; ++i) {
            ConvexHull hull = convexHulls[i];
            for (int j=0; j<hull.size; ++j) {
                nodeX[index] = hull.xVertices[j];
                nodeY[index] = hull.yVertices[j];

                if (nodeIndex[hull.yVertices[j]*sizeXPlusOne + hull.xVertices[j]] != index) throw new UnsupportedOperationException("ERROR " + nodeIndex[hull.yVertices[j]*sizeXPlusOne + hull.xVertices[j]] + " - " + index);
                ++index;
            }
        }
    }

    public final ConvexHullRPSScanner computeAllVisibleSuccessors(int currX, int currY) {
        scanner.computeAllVisibleSuccessors(currX, currY);
        return scanner;
    }

    public final int indexOf(int x, int y) {
        return nodeIndex[y*sizeXPlusOne + x];
    }

    public final int size() {
        return nNodes;
    }

    public final int getX(int index) {
        return nodeX[index];
    }

    public final int getY(int index) {
        return nodeY[index];
    }


    public final List<SnapshotItem> generateConvexHullSnapshot() {
        List<SnapshotItem> snapshotItemList = new ArrayList<>();

        for (int i=0; i<convexHulls.length; ++i) {
            ConvexHull hull = convexHulls[i];
            int size = hull.size;
            int prevX = hull.xVertices[size-1];
            int prevY = hull.yVertices[size-1];

            for (int j=0; j<size; ++j) {
                int currX = hull.xVertices[j];
                int currY = hull.yVertices[j];

                Integer[] path = new Integer[]{prevX, prevY, currX, currY};

                SnapshotItem snapshotItem = SnapshotItem.generate(path, Color.GREEN);
                snapshotItemList.add(snapshotItem);

                prevX = currX;
                prevY = currY;
            }
        }

        return snapshotItemList;
    }
    
}

@@ -998,16 +998,52 @@
 usOne%5D;%0A
+        Arrays.fill(nodeIndex, -1);%0A
     %7D%0A%0A 
@@ -1809,32 +1809,98 @@
 ll.yVertices%5Bj%5D;
+%0A                if (nodeIndex%5By*sizeXPlusOne +x%5D != -1) continue;
 %0A%0A              
@@ -2070,22 +2070,8 @@
     
-int index = 0;
 %0A   
@@ -2226,28 +2226,21 @@
         
-nodeX%5Bindex%5D
+int x
  = hull.
@@ -2269,28 +2269,21 @@
         
-nodeY%5Bindex%5D
+int y
  = hull.
@@ -2288,33 +2288,32 @@
 l.yVertices%5Bj%5D;%0A
-%0A
                 
@@ -2317,212 +2317,83 @@
    i
-f (nodeIndex%5Bhull.yVertices%5Bj%5D*sizeXPlusOne + hull.xVertices%5Bj%5D%5D != index) throw new UnsupportedOperationException(%22ERROR %22 + nodeIndex%5Bhull.yVertices%5Bj%5D*sizeXPlusOne + hull.xVertices%5Bj%5D%5D + %22 - %22 + index)
+nt index = nodeIndex%5By*sizeXPlusOne + x%5D;%0A%0A                nodeX%5Bindex%5D = x
 ;%0A  
@@ -2410,15 +2410,24 @@
     
-++index
+nodeY%5Bindex%5D = y
 ;%0A  

Fix errors with repeated nodes in convex hulls