package chess4j.utils;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.ParseException;
import java.util.List;

import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

import com.megginson.sax.XMLWriter;


import chess4j.App;
import chess4j.board.Board;
import chess4j.board.BoardImpl;
import chess4j.io.FenParser;
import chess4j.moves.Move;

public class Perft {
	
/*	Initial position
    Depth 	Perft(Depth) 	Total Nodes
    1 	20 	20
	2 	400 	420
	3 	8,902 	9322
	4 	197,281 	206,603
	5 	4,865,609 	5,072,212
	6 	119,060,324 	124,132,536
	7 	3,195,901,860 	3,320,034,396
*/
	
/*	r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq -
    Depth 	Perft(Depth) 	Total Nodes
	1 	48 	48
	2 	2039 	2087
	3 	97,862 	99,949
	4 	4,085,603 	4,185,552
	5 	193,690,690 	197,876,242
	6 	8,031,647,685
	Note: this exceeds 32 bits 	8,229,523,927	
*/	
	public static long perft(Board b,int depth,XMLWriter writer) throws SAXException {
		if (depth <= 0)
			return 1;

		if (writer != null) {
			writer.characters("\n");
			AttributesImpl att = new AttributesImpl();
			att.addAttribute("", "depth", "", "Integer", String.valueOf(depth));
			writer.startElement("","depth","", att);
		}
		
		List<Move> moves = App.getMoveGen().genLegalMoves(b);
		long n=1;

		for (Move m : moves) {
			if (writer != null) {
				writer.dataElement("move",m.toString());
			}
			b.applyMove(m);
			n += perft(b,depth-1,writer);
			b.undoLastMove();
		}
		if (writer != null) {
			writer.endElement("depth");
		}

		return n;
	}
	
	public static void main(String[] args) {
		int depth=3;
		
		//String fen="rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq -";
		String fen="r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq -";

		for (int i=0;i<args.length;i++) {
			String arg = args[i];
			if (arg.startsWith("depth=")) {
				depth = Integer.valueOf(arg.substring(6));
			} else if (arg.startsWith("fen=")) {
				fen = arg.substring(4);
			}
		}

		System.out.println("running perft(" + depth + ")... ");
		System.out.println("fen=" + fen);
		long start = System.currentTimeMillis();

		long n=0;
		try {
			XMLWriter w = new XMLWriter(new FileWriter(new File("perft.xml")));
			w.startDocument();
			Board b = new BoardImpl();
			FenParser.setPos(b, fen);
			n = Perft.perft(b,depth,w);
			w.endDocument();
		} catch (ParseException e) {
			e.printStackTrace();
			System.exit(1);
		} catch (SAXException e) {
			e.printStackTrace();
			System.exit(1);
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(1);
		}
	
		System.out.println("perft complete!");
		System.out.println("nodes: " + n);
		long end = System.currentTimeMillis();
		System.out.println("elapsed time: " + (end-start) + " ms");
		System.out.println("rate: " + n*1000/(end-start) + " n/s\n");
	}
}
