package chess4j.board;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Square {

	private static final List<Square> _squares = new ArrayList<Square>();
	private static Map<File,List<Square>> _fileSquares = new HashMap<File,List<Square>>();
	private static Map<Rank,List<Square>> _rankSquares = new HashMap<Rank,List<Square>>();

	private final Rank _rank;
	private final File _file;
	
	private Square(File file,Rank rank) {
		_file=file;
		_rank=rank;
	}

	static {
		for (File file : File.values()) {
			List<Square> squares = new ArrayList<Square>();
			for (Rank rank : Rank.values()) {
				squares.add(new Square(file,rank));
			}
			_fileSquares.put(file, squares);
		}
		
		for (Rank rank : Rank.values()) {
			List<Square> squares = new ArrayList<Square>();
			for (File file : File.values()) {
				squares.add(new Square(file,rank));
			}
			_rankSquares.put(rank, squares);
		}
	}

	static {
		for (Rank rank : Rank.values()) {
			for (File file : File.values()) {
				_squares.add(Square.valueOf(file, rank));
			}
		}
	}

	public Rank rank() { return _rank; }
	public File file() { return _file; }

	@Override
	public String toString() {
		return _file.getLabel() + _rank.getLabel();
	}
	
	public int value() {
		return _rank.getValue()*8 + _file.getValue();
	}
	
	public static Square valueOf(File file,Rank rank) {
		if (file==null || rank==null) return null;
		return _fileSquares.get(file).get(rank.getValue());
	}

	public static Square valueOf(Rank rank,File file) {
		if (file==null || rank==null) return null;
		return _rankSquares.get(rank).get(file.getValue());
	}

	public static List<Square> allSquares() {
		return Collections.unmodifiableList(_squares);
	}
	
	public static List<Square> fileSquares(File file) {
		return Collections.unmodifiableList(_fileSquares.get(file));
	}

	public static List<Square> rankSquares(Rank rank) {
		return Collections.unmodifiableList(_rankSquares.get(rank));
	}
	
	@Override
	public boolean equals(Object o) {
		if (!(o instanceof Square))
			return false;
		Square sq = (Square)o;
		return sq.file().equals(_file) && sq.rank().equals(_rank);
	}
	
	@Override
	public int hashCode() {
		return value();
	}
}
