/* Copyright 2018 Romain "Artefact2" Dal Maso <artefact2@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <assert.h>
#include <string.h>
#include "gumble.h"

static void assert_san_moves(const char* start_fen, const char* const* moves, const char* end_fen) {
	cch_board_t b, b2;
	cch_move_t m;
	assert(cch_load_fen(&b, start_fen) == CCH_OK);

	while(*moves) {
		assert(cch_parse_san_move(&b, *moves, &m) == CCH_OK);
		assert(cch_play_legal_move(&b, &m, 0) == CCH_OK);
		++moves;
	}

	char our_end_fen[SAFE_FEN_LENGTH];
	assert(cch_save_fen(&b, our_end_fen, SAFE_FEN_LENGTH) == CCH_OK);
	assert(!strcmp(our_end_fen, end_fen));

	assert(cch_load_fen(&b2, our_end_fen) == CCH_OK);
	assert(b.hash == b2.hash);
}

static void assert_san_move(const char* s, const char* m, const char* e) {
	const char* const moves[] = { m, 0 };
	assert_san_moves(s, moves, e);
}

static void assert_san_move_illegal(const char* fen, const char* move) {
	cch_board_t b;
	cch_move_t m;
	assert(cch_load_fen(&b, fen) == CCH_OK);
	assert(cch_parse_san_move(&b, move, &m) != CCH_OK);
}

int main(void) {
	const char* const moves1[] = {
		"c3", "e5",
		"d4", "Qf6",
		"f4", "c5",
		"Nf3", "exd4",
		"cxd4", "cxd4",
		"Nc3", "Bc5",
		"Nd5", "Qc6",
		"e4", "d3",
		"Bxd3", "d6",
		"Bb5", "Nd7",
		"Bxc6", 0
	};
	assert_san_moves(
		"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
		moves1,
		"r1b1k1nr/pp1n1ppp/2Bp4/2bN4/4PP2/5N2/PP4PP/R1BQK2R b KQkq - 0 11");

	const char* const moves2[] = {
		"Nfe7", "Nde5",
		"Rbe3", "R5d6",
		"Rh3", "N4a5",
		0
	};
	assert_san_moves(
		"k7/3r4/2n3N1/3r1N2/2n5/1R1n1R2/8/K7 w - - 0 1",
		moves2,
		"k7/3rN3/2nr2N1/n3n3/8/4R2R/8/K7 w - - 6 4");

	const char* const moves3[] = {
		"Rgd1", "Red8",
		"Ra5", "Rc5",
		"Rd6", "Rdc8",
		"Raa6", "R5c7",
		"Rdb6", 0
	};
	assert_san_moves(
		"2r1r2k/8/8/8/8/8/8/R5RK w - - 0 1",
		moves3,
		"2r4k/2r5/RR6/8/8/8/8/7K b - - 9 5");

	assert_san_move("r3k2r/pppppppp/8/8/8/8/PPPPPPPP/R3K2R w KQkq -", "O-O", "r3k2r/pppppppp/8/8/8/8/PPPPPPPP/R4RK1 b kq - 1 1");
	assert_san_move("r3k2r/pppppppp/8/8/8/8/PPPPPPPP/R3K2R w KQkq -", "O-O-O", "r3k2r/pppppppp/8/8/8/8/PPPPPPPP/2KR3R b kq - 1 1");
	assert_san_move("r3k2r/pppppppp/8/8/8/8/PPPPPPPP/R3K2R b KQkq -", "O-O", "r4rk1/pppppppp/8/8/8/8/PPPPPPPP/R3K2R w KQ - 1 2");
	assert_san_move("r3k2r/pppppppp/8/8/8/8/PPPPPPPP/R3K2R b KQkq -", "O-O-O", "2kr3r/pppppppp/8/8/8/8/PPPPPPPP/R3K2R w KQ - 1 2");

	const char* const moves4[] = {
		"f8=N", "e1=B",
		"h8=R", "g1=Q",
		0
	};
	assert_san_moves("8/k4P1P/8/8/8/8/K3p1p1/8 w - - 0 1", moves4, "5N1R/k7/8/8/8/8/K7/4b1q1 w - - 0 3");

	assert_san_move_illegal("8/k4P1P/8/8/8/8/K3p1p1/8 w - - 0 1", "f8");

	return 0;
}
