package sudoku.parse;

import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Scanner;
import java.util.function.Supplier;
import java.io.File;
import java.io.FileNotFoundException;
import sudoku.Puzzle;

/**
 * <p>Parses the initial puzzle out of a Sadman Sudoku puzzle file. This format is defined at
 * http://www.sadmansoftware.com/sudoku/faq19.php (retrieved 25 May 2016).</p> <p>All elements of a
 * Sadman format file other than the initial state of the puzzle are ignored, including the number
 * of solutions.</p>
 * @author fiveham
 * @author fiveham
 *
 */
public class SadmanParser implements Parser{
	
    /**
     * <p>Content of the line prior to the statement of the initial state of the puzzle.</p>
     */
	public static final String INITIAL_PUZZLE_MARKER = "[Puzzle]";
	
    /**
     * <p>Indicates an empty cell in the initial puzzle state.</p>
     */
	public static final char EMPTY_CELL = '.';
	
	private final int mag;
	private final List<Integer> values;
	
    /**
     * <p>Constructs a Parser that interprets the contents of the file {@code f} as a Sadman-format
     * sudoku puzzle, using the specified {@code charset} to read the file.</p>
     * @param f the file to be interpreted
     * @param charset the name of the charset to be used in reading the file. If the
     * @throws FileNotFoundException
     */
	public SadmanParser(File f, String charset) throws FileNotFoundException{
		this(() -> {
			try{
				return new Scanner(f, charset);
			} catch(FileNotFoundException e){
				throw new IllegalArgumentException(e);
			}
		});
	}
	
	public SadmanParser(File f) throws FileNotFoundException{
		this(() -> {
			try{
				return new Scanner(f);
			} catch(FileNotFoundException e){
				throw new IllegalArgumentException(e);
			}
		});
	}
	
	private SadmanParser(Supplier<Scanner> supplier) throws FileNotFoundException{
		Scanner s = supplier.get();
		while(s.hasNext() && !INITIAL_PUZZLE_MARKER.equals(s.nextLine()));
		
		if(!s.hasNext()){
			s.close();
			s = supplier.get();
		}
		
		StringBuilder initCells;
		try{
			initCells = new StringBuilder(s.nextLine());
			this.mag = (int)Math.sqrt(initCells.length());
			for(int i=1; i<mag*mag; ++i){
				initCells.append(s.nextLine());
			}
		} catch(NoSuchElementException e){
			throw new IllegalArgumentException("Could not parse the file as Sadman format", e);
		} finally{
			s.close();
		}
		this.values = new ArrayList<>(initCells.length());
		for(int i=0; i<initCells.length(); ++i){
			char c = initCells.charAt(i);
			values.add(c == EMPTY_CELL 
					? Puzzle.BLANK_CELL 
					: Integer.parseInt(Character.toString(c), mag*mag+1));
		}
	}
	
	@Override
	public int mag() {
		return mag;
	}
	
	@Override
	public List<Integer> values() {
		return values;
	}
}

@@ -138,44 +138,8 @@
 er;%0A
-import java.util.function.Supplier;%0A
 impo
@@ -1441,37 +1441,16 @@
 is(() -%3E
- %7B%0A%09%09%09try%7B%0A%09%09%09%09return
  new Sca
@@ -1465,29 +1465,60 @@
 charset)
+)
 ;%0A%09
-%09%09%7D catch(
+%7D%0A%09%0A%09public SadmanParser(File f) throws 
 FileNotF
@@ -1534,108 +1534,161 @@
 tion
- e)
 %7B%0A%09%09
-%09
-%09
 th
-row new IllegalArgumentException(e
+is(() -%3E new Scanner(f)
 );%0A
-%09%09
 %09%7D%0A%09
-%09%7D);%0A%09%7D%0A%09%0A%09public SadmanParser(File f)
+%0A%09/**%0A%09 * %3Cp%3EThis is a knockoff of %7B@literal java.util.function.Supplier%3CScanner%3E%7D that declares that it %0A%09 *
  throws 
 File
@@ -1675,32 +1675,34 @@
  it %0A%09 * throws 
+a 
 FileNotFoundExce
@@ -1710,149 +1710,358 @@
 tion
-%7B%0A%09%09this(() -%3E %7B%0A%09%09%09try%7B%0A%09%09%09%09return new Scanner(f);%0A%09%09%09%7D catch(FileNotFoundException e)%7B%0A%09%09%09%09throw new IllegalArgumentException(e);%0A%09%09%09%7D%0A%09%09%7D)
+ as part of its method header. This allows the two public %0A%09 * constructors to send Scanner-suppliers to the relevant constructor without needing to include %0A%09 * try-catch blocks inside the lambda bodies they send.%3C/p%3E%0A%09 * @author fiveham%0A%09 */%0A%09@FunctionalInterface%0A%09private interface FNFSupplier%7B%0A%09  public Scanner get() throws FileNotFoundException
 ;%0A%09%7D
@@ -2085,24 +2085,27 @@
 nParser(
+FNF
 Supplier
 %3CScanner
@@ -2096,25 +2096,16 @@
 Supplier
-%3CScanner%3E
  supplie

use adhoc interface to remove try-catch blocks from public constructors