package mm.structures;

import java.util.Random;

/**
 * Square matrix (n x n) of m (colorCount) colors.
 */
public class ColorField extends Matrix {

    private int n, colorCount;
    private int[][] neighbourMask;
    private ColorPixel[] colors;

    /**
     * Initialize mm.structures.ColorField as n x n matrix using given colors array as colors.
     *
     * @param n      - Dimension of matrix.
     * @param colors - Colors to be used in field.
     */
    public ColorField(int n, ColorPixel[] colors) {
        super(n);
        init(colors);
    }

    /**
     * Initialize mm.structures.ColorField as n x n matrix using given colors array as colors.
     *
     * @param array  - Array representing the field matrix.
     * @param colors - Colors to be used in field.
     */
    private ColorField(int[][] array, ColorPixel[] colors) {
        super(array);
        init(colors);
        colors = colors != null ? colors : new ColorPixel[0];
    }

    /**
     * Initialize colors array and color map (array of ints representing colors).
     * @param colors - Colors to be used in field.
     */
    private void init(ColorPixel[] colors) {
        this.n = super.n;
        this.colors = colors;
        this.colorCount = colors.length;
        // Set codes for each color.
        for(int i = 0; i < colorCount; i++) {
            colors[i].setCode(i);
        }
        // Calculate neighbourMask array in advance, used to improve performance
        //  compared to calculating indices for every `getNeighbours` lookup.
        neighbourMask = new int[super.length][8];
        for (int i = 0, index = 0; i < m; i++) {
            for (int j = 0; j < n; j++, index++) {
                for (int ii = i - 1, ind = 0; ii <= i + 1; ii++) {
                    for (int jj = j - 1; jj <= j + 1; jj++) {
                        if (ii == i && jj == j) {
                            continue;
                        }
                        neighbourMask[index][ind++] =
                                ((ii < 0 || ii >= m) || (jj < 0 || jj >= n))
                                        ? -1 : indexOf(ii, jj);
                    }
                }
            }
        }
    }

    public int getN() {
        return n;
    }

    public int getColorCount() {
        return colorCount;
    }

    public ColorPixel[] getColors() {
        return colors;
    }

    /**
     * Find values of neighbours of (i, j).
     *
     * @param i - mm.structures.Matrix row.
     * @param j - mm.structures.Matrix column.
     * @return - Vector (1x8) of neighbours. If neighbour index is out of bounds, -1 is used as value.
     */
    public int[] getNeighbours(int i, int j) {
        int[] map = neighbourMask[indexOf(i, j)];
        int[] neighbours = new int[8];
        for (int ii = 0; ii < 8; ii++) {
            neighbours[ii] = map[ii] == -1 ? -1 : a[map[ii]];
        }
        return neighbours;
    }

    public static ColorField GenerateField(int n, ColorPixel[] colors) {
        ColorField cf = new ColorField(n, colors);
        Random r = new Random();
        for(int i = 0; i < cf.length; i++) {
            cf.setElement1D(i, colors[r.nextInt(cf.colorCount)].getCode());
        }
        return cf;
    }
}

@@ -542,27 +542,207 @@
  init(colors
+, true);%0A    %7D%0A%0A    private ColorField(int n, ColorPixel%5B%5D colors, int%5B%5D%5B%5D neighbourMask) %7B%0A        super(n);%0A        this.neighbourMask = neighbourMask;%0A        init(colors, false
 );%0A
-
     %7D%0A%0A    /
@@ -1052,30 +1052,8 @@
 y);%0A
-        init(colors);%0A
     
@@ -1110,16 +1110,44 @@
 xel%5B0%5D;%0A
+        init(colors, true);%0A
     %7D%0A%0A 
@@ -1327,32 +1327,64 @@
 orPixel%5B%5D colors
+, boolean calculateNeighbourMask
 ) %7B%0A        this
@@ -1587,32 +1587,73 @@
 e(i);%0A        %7D%0A
+        if(calculateNeighbourMask) %7B%0A    
         // Calcu
@@ -1725,16 +1725,20 @@
         
+   
+ 
 //  comp
@@ -1799,32 +1799,36 @@
 lookup.%0A        
+    
 neighbourMask = 
@@ -1853,32 +1853,36 @@
 th%5D%5B8%5D;%0A        
+  
+  
 for (int i = 0, 
@@ -1910,32 +1910,36 @@
 ) %7B%0A            
+    
 for (int j = 0; 
@@ -1969,32 +1969,36 @@
                 
+ 
+   
 for (int ii = i 
@@ -2044,32 +2044,36 @@
                 
+    
 for (int jj = j 
@@ -2122,16 +2122,20 @@
         
+ 
+   
 if (ii =
@@ -2148,24 +2148,28 @@
  jj == j) %7B%0A
+    
             
@@ -2210,34 +2210,42 @@
                 
-%7D%0A
+    %7D%0A    
                 
@@ -2314,16 +2314,20 @@
         
+    
 ((ii %3C 0
@@ -2403,16 +2403,20 @@
         
+  
+  
 ? -1 : i
@@ -2431,16 +2431,42 @@
 i, jj);%0A
+                        %7D%0A
         

add constructor that accepts neighbourMask array