use std::io::{Write, BufWriter};
static BOARD_SIZE: usize = 10;	// 盤面のコマ+2

#[derive(Debug, Clone)]
pub enum PieceType {
	Black,
	White,
	Sentinel,
	Null,
}

fn flip_turn(t: PieceType) -> PieceType {
	match t {
		PieceType::Black => PieceType::White,
		PieceType::White => PieceType::Black,
		_ => PieceType::Null,
	}
}


#[derive(Debug, Clone)]
pub struct Reversi {
	board: Vec<Vec<PieceType>>,
	pub turn: PieceType,
}

impl Reversi {
	pub fn new() -> Self {
		let mut v: Vec<Vec<PieceType>> = Vec::new();
		let half = (BOARD_SIZE - 2) / 2;
		for y in 0..BOARD_SIZE {
			v.push(Vec::new());
			for x in 0..BOARD_SIZE {
				if y == 0 || x == 0 ||
				y == BOARD_SIZE - 1 || x == BOARD_SIZE - 1 {
					v[y].push(PieceType::Sentinel);
				} else if y == half && x == half ||
				y == half + 1 && x == half + 1 {
					v[y].push(PieceType::White);
				} else if y == half && x == half  + 1 ||
				y == half + 1 && x == half {
					v[y].push(PieceType::Black);
				} else {
					v[y].push(PieceType::Null);
				}
			}
		}

		Reversi {
			board: v,
			turn: PieceType::Black,
		}
	}

	pub fn debug_board(&self) {
		let w = super::std::io::stdout();
		let mut w = BufWriter::new(w.lock());
		for _i in 0..BOARD_SIZE {
			write!(w, "+-").expect("stdout Error");
		}
		writeln!(w, "+").expect("stdout Error");
		for y in &self.board {
			write!(w, "|").expect("stdout Error");
			for x in y {
				write!(w, "{}|", match *x {
					PieceType::Black => "x",
					PieceType::White => "o",
					PieceType::Null => " ",
					PieceType::Sentinel => "=",
					//_ => "",
				}).expect("stdout Error");
			}
			writeln!(w, "").expect("stdout Error");
			for _i in 0..BOARD_SIZE {
				write!(w, "+-").expect("stdout Error");
			}
			writeln!(w, "+").expect("stdout Error");
		}
	}

	pub fn show_turn(&self) {
		println!("turn: {}", match self.turn {
			PieceType::Black => "Black",
			PieceType::White => "White",
			_ => "Something wrong.",
		})
	}

	pub fn turn_change(self) -> Self {
		Reversi {
			board: self.board,
			turn: flip_turn(self.turn),
		}
	}

	pub fn show_score(&self) {
		let mut black = 0;
		let mut white = 0;
		for y in &self.board {
			for x in y {
				match *x {
					PieceType::White => white += 1,
					PieceType::Black => black += 1,
					_ => {},
				};
			}
		}
		let w = super::std::io::stdout();
		let mut w = BufWriter::new(w.lock());
		writeln!(w, "+---------+").expect("stdout Error");
		writeln!(w, "|  Score  |").expect("stdout Error");
		writeln!(w, "+---------+").expect("stdout Error");
		writeln!(w, "|Black|{:03}|", black).expect("stdout Error");
		writeln!(w, "+-----+---+").expect("stdout Error");
		writeln!(w, "|White|{:03}|", white).expect("stdout Error");
		writeln!(w, "+-----+---+").expect("stdout Error");
	}

/*
	fn is_placeable(&self, x: usize, y: usize, r: usize) -> bool {
		let nt = flip_turn(self.turn.clone());
		match self.board[y][x] {
			PieceType::Null => {},
			_ => return false,
		};
		let (iy, ix) = match r {
			0 => (-1, -1), 1 => (-1, 0), 2 => (-1, 1),
			3 => (0, -1), 4 => (0, 0), 5 => (0, 1),
			6 => (1, -1), 7 => (1, 0), 8 => (1, 1),
			_ => (0, 0),
		};
		let mut b = false;
		let mut _y = y as isize;
		let mut _x = x as isize;
		loop {
			_y += iy;
			_x += ix;
			if _y < 0 || _x < 0 {
				return false;
			}
			if self.board[_y as usize][_x as usize] == nt {
				b = true;
			} else if b && self.board[_y as usize][_x as usize] == self.turn {
				return true;
			} else {
				return false;
			}
		}
	}
	pub fn put(self, x: usize, y: usize) -> Result<Self> {

	}
*/
	pub fn continue_game(&self) -> bool {
		let mut null = 0;
		for y in &self.board {
			for x in y {
				match *x {
					PieceType::Null => null += 1,
					_ => {},
				}
			}
		}
		if null == 0 {
			return false;
		}
		true
	}
}
impl PartialEq for PieceType {
	fn eq(&self, t: &PieceType) -> bool {
		self == t
	}
}