package mc.mcgrizzz.prorecipes.recipes;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;

import mc.mcgrizzz.prorecipes.ProRecipes;
import mc.mcgrizzz.prorecipes.lib.ItemUtils;
import mc.mcgrizzz.prorecipes.lib.Pair;

public class RecipeChest {
	
	String idCache = "";
	
	HashMap<Character, ItemStack> ingredients = new HashMap<Character, ItemStack>();
	ItemStack[] results = new ItemStack[4];
	String[][] structure;
	ItemStack[][] itemsCache;
	String permission;

	
	public RecipeChest(ItemStack[] it){
		results = it.clone();
	
	}
	
	
	public void setPermission(String s){
		this.permission = s;
	}
	
	public String getPermission(){
		return this.permission;
	}
	
	public boolean hasPermission(){
		return permission != null && !permission.isEmpty();
	}
	
	
	public void setIngredients(HashMap<Character, ItemStack> in){
		this.ingredients = in;
		for(Character c : in.keySet()){
			if(c == ' ')continue;
			if(in.get(c).getType().equals(Material.AIR))continue;
		}
	}
	
	public ItemStack[] getItems(){
		ItemStack[] items = new ItemStack[16];
		
		ItemStack[][] i = new ItemStack[structure.length][structure[0].length];
		for(int t = 0; t < i.length; t++){
			for(int z = 0; z <i[t].length; z++){
				
				if(structure[t][z] == null){
					i[t][z] = new ItemStack(Material.AIR, 0);
					continue;
				}
				if(structure[t][z].toCharArray().length <= 0 ||ingredients.get(structure[t][z].toCharArray()[0]) == null){
					i[t][z] = new ItemStack(Material.AIR, 0);
					continue;
				}
				i[t][z] = ingredients.get(structure[t][z].toCharArray()[0]);
			}
		}
		
		items = toOneD(i);
		return items;
	}
	
	
	public String getId(){
		if(!idCache.isEmpty()){
			return idCache;
		}
		String[][] i = new String[structure.length][structure[0].length];
		ItemStack[][] k = new ItemStack[structure.length][structure[0].length];
		for(int t = 0; t < i.length; t++){
			for(int z = 0; z <i[t].length; z++){
				if(structure.length < t || structure[t].length < z){
					continue;
				}
				
				if(structure[t][z] == null){
					i[t][z] = ProRecipes.airString;
					k[t][z] = new ItemStack(Material.AIR, 0);
					continue;
				}
				if(structure[t][z].toCharArray().length <= 0) {
					i[t][z] = ProRecipes.airString;
					k[t][z] = new ItemStack(Material.AIR, 0);
					continue;
				}
				
				if(ingredients.get(structure[t][z].toCharArray()[0]) == null){
					i[t][z] = ProRecipes.airString;
					k[t][z] = new ItemStack(Material.AIR, 0);
					continue;
				}
				ItemStack it = ingredients.get(structure[t][z].toCharArray()[0]);
				k[t][z] = it.clone();
				i[t][z] = ItemUtils.itemToStringBlob(it);
			}
		}
		idCache = Arrays.deepToString(convertToMinimizedStructure(i, ProRecipes.airString));
		itemsCache = convertToMinimizedStructure(k);
		return idCache;
 	}
	
	public String getId(ItemStack[][] i){
		String k = "";
		String[][] b = new String[i.length][i[0].length];
		for(int t = 0; t < i.length; t++){
			for(int z = 0; z <i[t].length; z++){
				if(i.length < t || i[t].length < z){
					continue;
				}
				if(i[t][z] == null){
					b[t][z] = ProRecipes.airString;
					continue;
				}
				if(i[t][z].getType().equals(Material.AIR)){
					i[t][z] = new ItemStack(Material.AIR);
				}
				b[t][z] = ItemUtils.itemToStringBlob(i[t][z]);
			}
		}
		k = Arrays.deepToString(convertToMinimizedStructure(b, ProRecipes.airString));
		return k;
	}
	
	public static ItemStack[][] convertToArray(ItemStack[] i){
		if(i.length / 4 == 4){
			ItemStack[][] arr = new ItemStack[4][4];
			for(int x = 0; x < 4; x++){
				for(int z = 0; z < 4; z++){
					if(i[x*4 + z] == null){
						arr[x][z] = new ItemStack(Material.AIR, 0);
						continue;
					}
					arr[x][z] = i[x*4 + z]; 
				}
			}
			return arr;
 		}else{
			return null;
		}
	}
	
	
 	
	public static ItemStack[][] convertToMinimizedStructure(ItemStack[][] i){
		int x = i.length-1;
		//Check first row
		boolean clear = true;
		boolean fClear = true;
		for(int z = 0; z < i[0].length; z++){
			if(i[0][z] == null)continue;
			if(i[0][z] != null && !i[0][z].getType().equals(Material.AIR)){
				clear = false;
				fClear = false;
				break;
			}
		}
		if(clear){
			i = copyIgnore(ItemStack.class, i, 0, -1);
			x--;
			
		}
		
		
		//Check last row
		clear = true;
		boolean lClear = true;
		for(int z = 0; z < i[x].length; z++){
			if(i[x][z] == null)continue;
			if(i[x][z] != null && !i[x][z].getType().equals(Material.AIR)){
				clear = false;
				lClear = false;
				break;
			}
		}
		if(clear){
			i = copyIgnore(ItemStack.class, i, x, -1);
			x--;
		}
		
		//Only check middle row if one is empty
		if((fClear || lClear) && !(fClear && lClear)){
			if(fClear){
				clear = true;
				for(int z = 0; z < i[0].length; z++){
					if(i[0][z] == null)continue;
					if(i[0][z] != null && !i[0][z].getType().equals(Material.AIR)){
						clear = false;
						break;
					}
				}
				//if clear check for next first column
				if(clear){
					i = copyIgnore(ItemStack.class, i, 0, -1);
					x--;
					//clear
					clear = true;
					for(int z = 0; z < i[0].length; z++){
						if(i[0][z] == null)continue;
						if(i[0][z] != null && !i[0][z].getType().equals(Material.AIR)){
							clear = false;
							break;
						}
					}
					
					if(clear){
						i = copyIgnore(ItemStack.class, i, 0, -1);
						x--;
						
						
					}
					
				}
			}else{
				clear = true;
				for(int z = 0; z < i[i.length-1].length; z++){
					if(i[i.length-1][z] == null)continue;
					if(i[i.length-1][z] != null && !i[i.length-1][z].getType().equals(Material.AIR)){
						clear = false;
						break;
					}
				}
				if(clear){
					i = copyIgnore(ItemStack.class, i, i.length-1, -1);
					x--;
					
					//if clear check next last row
					for(int z = 0; z < i[i.length-1].length; z++){
						if(i[i.length-1][z] == null)continue;
						if(i[i.length-1][z] != null && !i[i.length-1][z].getType().equals(Material.AIR)){
							clear = false;
							break;
						}
					}
					if(clear){
						i = copyIgnore(ItemStack.class, i, i.length-1, -1);
						x--;
						
					}
					
				}
			}
			
		}else if(fClear && lClear){
			clear = true;
			for(int z = 0; z < i[0].length; z++){
				if(i[0][z] == null)continue;
				if(i[0][z] != null && !i[0][z].getType().equals(Material.AIR)){
					clear = false;
					break;
				}
			}
			//if clear check for next first column
			if(clear){
				i = copyIgnore(ItemStack.class, i, 0, -1);
				x--;
			}else{
				
				clear = true;
				for(int z = 0; z < i[i.length-1].length; z++){
					if(i[i.length-1][z] == null)continue;
					if(i[i.length-1][z] != null && !i[i.length-1][z].getType().equals(Material.AIR)){
						clear = false;
						break;
					}
				}
				if(clear){
					i = copyIgnore(ItemStack.class, i, i.length-1, -1);
					x--;
				}
			}
		}
		
		
		//GO THROUGH COLUMNS
		
		int z = i[0].length-1;
		//Check first row
		clear = true;
		fClear = true;
		for(int xX = 0; xX < i.length; xX++){
			if(i[xX][0] == null)continue;
			if(i[xX][0] != null && !i[xX][0].getType().equals(Material.AIR)){
				clear = false;
				fClear = false;
				break;
			}
		}
		if(clear){
			i = copyIgnore(ItemStack.class, i, -1, 0);
			z--;
			
		}
		
		
		//Check last row
		clear = true;
		lClear = true;
		for(int xX = 0; xX < i.length; xX++){
			if(i[xX][z] == null)continue;
			if(i[xX][z] != null && !i[xX][z].getType().equals(Material.AIR)){
				clear = false;
				lClear = false;
				break;
			}
		}
		if(clear){
			i = copyIgnore(ItemStack.class, i, -1, z);
			z--;
		}
		
		//Only check middle row if one is empty
		if((fClear || lClear) && !(fClear && lClear)){
			if(fClear){
				clear = true;
				for(int xX = 0; xX < i.length; xX++){
					if(i[xX][0] == null)continue;
					if(i[xX][0] != null && !i[xX][0].getType().equals(Material.AIR)){
						clear = false;
						break;
					}
				}
				if(clear){
					i = copyIgnore(ItemStack.class, i, -1, 0);
					z--;
					for(int xX = 0; xX < i.length; xX++){
						if(i[xX][0] == null)continue;
						if(i[xX][0] != null && !i[xX][0].getType().equals(Material.AIR)){
							clear = false;
							break;
						}
					}
					if(clear){
						i = copyIgnore(ItemStack.class, i, -1, 0);
						z--;
						
					}
					
				}
			}else{
				clear = true;
				for(int xX = 0; xX < i.length; xX++){
					if(i[xX][z] == null)continue;
					if(i[xX][z] != null && !i[xX][z].getType().equals(Material.AIR)){
						clear = false;
						break;
					}
				}
				if(clear){
					i = copyIgnore(ItemStack.class, i, -1, z);
					z--;
					for(int xX = 0; xX < i.length; xX++){
						if(i[xX][z] == null)continue;
						if(i[xX][z] != null && !i[xX][z].getType().equals(Material.AIR)){
							clear = false;
							break;
						}
					}
					if(clear){
						i = copyIgnore(ItemStack.class, i, -1, z);
						z--;
					}
				}
			}
			
		}else if(fClear && lClear){
			
			clear = true;
			for(int xX = 0; xX < i.length; xX++){
				if(i[xX][0] == null)continue;
				if(i[xX][0] != null && !i[xX][0].getType().equals(Material.AIR)){
					clear = false;
					break;
				}
			}
			if(clear){
				i = copyIgnore(ItemStack.class, i, -1, 0);
				z--;
			}else{
				clear = true;
				for(int xX = 0; xX < i.length; xX++){
					if(i[xX][z] == null)continue;
					if(i[xX][z] != null && !i[xX][z].getType().equals(Material.AIR)){
						clear = false;
						break;
					}
				}
				if(clear){
					i = copyIgnore(ItemStack.class, i, -1, z);
					z--;
					
				}
			}
			
		}
		
		return i;
	}
	
	protected static String[][] convertToMinimizedStructure(String[][] i, String filter){
		
	
				int x = i.length-1;
				boolean clear = true;
				boolean fClear = true;
				for(int z = 0; z < i[0].length; z++){
					if(i[0][z] == null)continue;
					if(i[0][z] != null && !i[0][z].isEmpty() && !i[0][z].equals(filter)){
						clear = false;
						fClear = false;
						break;
					}
				}
				if(clear){
					i = copyIgnore(String.class, i, 0, -1);
					x--;
					
				}
				
				
				//Check last row
				clear = true;
				boolean lClear = true;
				for(int z = 0; z < i[x].length; z++){
					if(i[x][z] == null)continue;
					if(i[x][z] != null && !i[x][z].isEmpty() && !i[x][z].equals(filter)){
						clear = false;
						lClear = false;
						break;
					}
				}
				if(clear){
					i = copyIgnore(String.class, i, x, -1);
					x--;
				}
				
				//Only check middle row if one is empty
				if((fClear || lClear) && !(fClear && lClear)){
					if(fClear){
						clear = true;
						for(int z = 0; z < i[0].length; z++){
							if(i[0][z] == null)continue;
							if(i[0][z] != null && !i[0][z].isEmpty() && !i[0][z].equals(filter)){
								clear = false;
								break;
							}
						}
						//if clear check for next first column
						if(clear){
							i = copyIgnore(String.class, i, 0, -1);
							x--;
							//clear
							clear = true;
							for(int z = 0; z < i[0].length; z++){
								if(i[0][z] == null)continue;
								if(i[0][z] != null && !i[0][z].isEmpty() && !i[0][z].equals(filter)){
									clear = false;
									break;
								}
							}
							
							if(clear){
								i = copyIgnore(String.class, i, 0, -1);
								x--;
								
								
							}
							
						}
					}else{
						clear = true;
						for(int z = 0; z < i[i.length-1].length; z++){
							if(i[i.length-1][z] == null)continue;
							if(i[i.length-1][z] != null && !i[i.length-1][z].isEmpty() && !i[i.length-1][z].equals(filter)){
								clear = false;
								break;
							}
						}
						if(clear){
							i = copyIgnore(String.class, i, i.length-1, -1);
							x--;
							
							//if clear check next last row
							for(int z = 0; z < i[i.length-1].length; z++){
								if(i[i.length-1][z] == null)continue;
								if(i[i.length-1][z] != null && !i[i.length-1][z].isEmpty() && !i[i.length-1][z].equals(filter)){
									clear = false;
									break;
								}
							}
							if(clear){
								i = copyIgnore(String.class, i, i.length-1, -1);
								x--;
								
							}
							
						}
					}
					
				}else if(fClear && lClear){
					clear = true;
					for(int z = 0; z < i[0].length; z++){
						if(i[0][z] == null)continue;
						if(i[0][z] != null && !i[0][z].isEmpty() && !i[0][z].equals(filter)){
							clear = false;
							break;
						}
					}
					//if clear check for next first column
					if(clear){
						i = copyIgnore(String.class, i, 0, -1);
						x--;
					}else{
						
						clear = true;
						for(int z = 0; z < i[i.length-1].length; z++){
							if(i[i.length-1][z] == null)continue;
							if(i[i.length-1][z] != null && !i[i.length-1][z].isEmpty() && !i[i.length-1][z].equals(filter)){
								clear = false;
								break;
							}
						}
						if(clear){
							i = copyIgnore(String.class, i, i.length-1, -1);
							x--;
						}
					}
				}
				
				
				//GO THROUGH COLUMNS
				
				int z = i[0].length-1;
				//Check first row
				clear = true;
				fClear = true;
				for(int xX = 0; xX < i.length; xX++){
					if(i[xX][0] == null)continue;
					if(i[xX][0] != null && !i[xX][0].isEmpty() && !i[xX][0].equals(filter)){
						clear = false;
						fClear = false;
						break;
					}
				}
				if(clear){
					i = copyIgnore(String.class, i, -1, 0);
					z--;
					
				}
				
				
				//Check last row
				clear = true;
				lClear = true;
				for(int xX = 0; xX < i.length; xX++){
					if(i[xX][z] == null)continue;
					if(i[xX][z] != null && !i[xX][z].isEmpty() && !i[xX][z].equals(filter)){
						clear = false;
						lClear = false;
						break;
					}
				}
				if(clear){
					i = copyIgnore(String.class, i, -1, z);
					z--;
				}
				
				//Only check middle row if one is empty
				if((fClear || lClear) && !(fClear && lClear)){
					if(fClear){
						clear = true;
						for(int xX = 0; xX < i.length; xX++){
							if(i[xX][0] == null)continue;
							if(i[xX][0] != null && !i[xX][0].isEmpty() && !i[xX][0].equals(filter)){
								clear = false;
								break;
							}
						}
						if(clear){
							i = copyIgnore(String.class, i, -1, 0);
							z--;
							for(int xX = 0; xX < i.length; xX++){
								if(i[xX][0] == null)continue;
								if(i[xX][0] != null && !i[xX][0].isEmpty() && !i[xX][0].equals(filter)){
									clear = false;
									break;
								}
							}
							if(clear){
								i = copyIgnore(String.class, i, -1, 0);
								z--;
								
							}
							
						}
					}else{
						clear = true;
						for(int xX = 0; xX < i.length; xX++){
							if(i[xX][z] == null)continue;
							if(i[xX][z] != null && !i[xX][z].isEmpty() && !i[xX][z].equals(filter)){
								clear = false;
								break;
							}
						}
						if(clear){
							i = copyIgnore(String.class, i, -1, z);
							z--;
							for(int xX = 0; xX < i.length; xX++){
								if(i[xX][z] == null)continue;
								if(i[xX][z] != null && !i[xX][z].isEmpty() && !i[xX][z].equals(filter)){
									clear = false;
									break;
								}
							}
							if(clear){
								i = copyIgnore(String.class, i, -1, z);
								z--;
							}
						}
					}
					
				}else if(fClear && lClear){
					
					clear = true;
					for(int xX = 0; xX < i.length; xX++){
						if(i[xX][0] == null)continue;
						if(i[xX][0] != null && !i[xX][0].isEmpty() && !i[xX][0].equals(filter)){
							clear = false;
							break;
						}
					}
					if(clear){
						i = copyIgnore(String.class, i, -1, 0);
						z--;
					}else{
						clear = true;
						for(int xX = 0; xX < i.length; xX++){
							if(i[xX][z] == null)continue;
							if(i[xX][z] != null && !i[xX][z].isEmpty() && !i[xX][z].equals(filter)){
								clear = false;
								break;
							}
						}
						if(clear){
							i = copyIgnore(String.class, i, -1, z);
							z--;
						}
					}
					
				}
		
		
	
		
		return i;
	}
	
	
	public static Pair<String[][], HashMap<Character, ItemStack>> getStructure(ItemStack[][] i){
		Character[] chars = {'a','b','c','d','e','f','g','h','i', 'j','k','l', 'm', 'n', 'o', 'p'};
		ItemStack[][] min = convertToMinimizedStructure(i);
		String[][] st = new String[min.length][min[0].length];
		HashMap<Character, ItemStack> keys = new HashMap<Character, ItemStack>();
		for(int x = 0; x < min.length; x++){
			for(int z = 0; z < min[x].length; z++){
					Character b = chars[keys.keySet().size()];
					st[x][z] = b.toString();
					keys.put(b, min[x][z]);
				}
			}
		
		return new Pair<String[][], HashMap<Character, ItemStack>>(st, keys);
	}
	
	public String[] toOneD(String[][] s){
		String[] nS = new String[s.length];
		for(int x = 0; x < s.length; x++){
			String t = "";
			if(s[x]== null){
				nS[x] = " ";
			}
			for(int z = 0; z < s[x].length; z++){
					if(s[x][z] == null){
						t+=" ";
					}else{
						t += s[x][z];
					}
					
			}
			nS[x] = t;
		}
		
		return nS;
 	}
	
	public ItemStack[] toOneD(ItemStack[][] s){
		ItemStack[] items = new ItemStack[16];
		for(int x = 0; x < 4; x++){
			for(int z = 0; z < 4; z++){
				if(x >= s.length || z >= s[x].length){
					items[x*4 + z] = null;
				}else{
					items[x*4 + z] = s[x][z];
				}
			}
		}
		
		return items;
	}
	
	
	public void setStructure(String[][] s){
		this.structure = s;
	}
	
	public void setIngredient(ItemStack it, Character i){
		
		if(it.getType() != Material.AIR){
			ingredients.put(i, it);
		}
		
	}
	
	public boolean matchMaps(Map<Character, ItemStack> a, Map<Character, ItemStack> b){
		boolean match = true;
		
		ArrayList<Character> setAir = new ArrayList<Character>();
		a.remove(" ");
		b.remove(" ");
		for(Character s : a.keySet()){
			if(a.get(s) == null){
				setAir.add(s);
			}
		}
		for(Character s : setAir){
			a.put(s, new ItemStack(Material.AIR));
		}
		
		setAir.clear();
		
		for(Character s : a.keySet()){
			if(b.get(s) == null){
				setAir.add(s);
			}
		}
		
		for(Character s : setAir){
			b.put(s, new ItemStack(Material.AIR));
		}
		
		ArrayList<String> aS = new ArrayList<String>();
		ArrayList<String> bS = new ArrayList<String>();
		
		for(java.util.Map.Entry<Character, ItemStack> e : a.entrySet()){
			String item = e.getValue() != null ? ItemUtils.itemToStringBlob(e.getValue()) : "null";
			aS.add(e.getKey().toString() + " " + item);
		}
		for(java.util.Map.Entry<Character, ItemStack> e : b.entrySet()){
			String item = e.getValue() != null ? ItemUtils.itemToStringBlob(e.getValue()) : "null";
			bS.add(e.getKey().toString() + " " + item);
		}
		
		for(String s : aS){
			if(!bS.contains(s)){
				match = false;
				break;
			}
		}
		for(String s : bS){
			if(!aS.contains(s)){
				match = false;
				break;
			}
		}
		
		
		return match;
	}
	
	public boolean register(){
		
		return ProRecipes.getPlugin().getRecipes().addChest(this);
	}
	
	public ItemStack[] getResult(){
		return this.results;
	}
	
	public ItemStack getDisplayResult(){
		ItemStack d = new ItemStack(Material.AIR);
		for(ItemStack i : results){
			if(i != null && !i.getType().equals(Material.AIR)){
				d = i.clone();
				break;
			}
		}
		
		return d;
	}
	
	
	
	public boolean matchLowest(RecipeChest i){
		if(!match(i)){
			ItemStack[][] passItems = convertToMinimizedStructure(i.itemsCache);
			ItemStack[][] meItems = convertToMinimizedStructure(itemsCache);
			if(passItems.length != meItems.length){
				return false;
			}
			if(passItems[0].length != meItems[0].length){
				return false;
			}
			for(int x = 0; x < passItems.length; x++){
				for(int z = 0; z < passItems[x].length; z++){
					ItemStack compare = passItems[x][z].clone();
					ItemStack orig = meItems[x][z].clone();
					if(orig == null || orig.getType().equals(Material.AIR)){
						if(compare == null || compare.getType().equals(Material.AIR)){
							continue;
						}else{
							return false;
						}
					}
					if(compare.getAmount()  >= orig.getAmount()){
						System.out.println(ItemUtils.itemToStringBlob(compare));
						System.out.println(ItemUtils.itemToStringBlob(orig));
						return false;
					}
					compare.setAmount(orig.getAmount());
					if(!ItemUtils.itemToStringBlob(compare).equals(ItemUtils.itemToStringBlob(orig))){
						return false;
					}
				}
			}
			return true;
		}else{
			return true;
		}
		
	}
	
	//Is this the same recipe as the passed recipe
	public boolean match(ItemStack[][] i){
		String a = getId().replaceAll("\\[", "").replaceAll("\\]","").replaceAll("\\{", "").replaceAll("\\}","").replaceAll(" =null, ", "").replaceAll(",  =null", "");
		String b = getId(i).replaceAll("\\[", "").replaceAll("\\]","").replaceAll("\\{", "").replaceAll("\\}","").replaceAll(" =null, ", "").replaceAll(",  =null", "");
		return a.equalsIgnoreCase(b);
	}
	
	public boolean match(RecipeChest p){
		String a = getId().replaceAll("\\[", "").replaceAll("\\]","").replaceAll("\\{", "").replaceAll("\\}","").replaceAll(" =null, ", "").replaceAll(",  =null", "");
		if(p == null){
			return false;
		}
		
		String b = p.getId().replaceAll("\\[", "").replaceAll("\\]","").replaceAll("\\{", "").replaceAll("\\}","").replaceAll(" =null, ", "").replaceAll(",  =null", "");
		
		return a.equalsIgnoreCase(b);
	}
	
	/**
	 * Copies an array removing either a column or row or both. Uses reflection, oops.
	 * @param arr The array to copy data from. Must be rectangular!s
	 * @param skRow The row to skip, or -1 to skip no rows
	 * @param skCol The col to skip, or -1 to skip no columns
	 * @return An array missing the specified columns and rows
	 */
	@SuppressWarnings("unchecked")
	protected static <T> T[][] copyIgnore(Class<T> cl, T[][] arr, int skRow, int skCol) {
	        if (skRow == -1 && skCol == -1)
	                return arr;
	 
	        if (arr.length == 0 || (arr.length == 1 && skRow != -1) || arr[0].length == 0 || (arr[0].length == 1 && skCol != -1))
	                return (T[][]) Array.newInstance(cl, 0, 0);
	 
	        // Strip out the specified row
	        if (skRow != -1) {
	                T[][] newArr = (T[][]) Array.newInstance(cl, arr.length - 1, arr[0].length);
	 
	                for (int origRow = 0; origRow < arr.length; origRow++) {
	                        int newRow = origRow;
	                        if (newRow == skRow) continue; //  skip specified row
	                        if (newRow > skRow) newRow--; // fix index
	 
	                        for (int col = 0; col < arr[0].length; col++) {
	                                newArr[newRow][col] = arr[origRow][col];
	                        }
	                }
	 
	                // Now strip out the specified column
	                return copyIgnore(cl, newArr, -1, skCol);
	        }
	 
	        // Strip out the specified column
	        T[][] newArr = (T[][]) Array.newInstance(cl, arr.length, arr[0].length - 1);
	 
	        for (int row = 0; row < arr.length; row++) {
	                for (int origCol = 0; origCol < arr[0].length; origCol++) {
	                        int newCol = origCol;
	                        if (newCol == skCol) continue; // skip specified col
	                        if (newCol > skCol) newCol--; // fix index
	                       
	                        newArr[row][newCol] = arr[row][origCol];
	                }
	        }
	 
	        return newArr;
	}
	

}