package somiba.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import somiba.domain.Player;


public class MySqlPlayerDao extends AbstractDatabaseDao implements PlayerDao {

	@Override
	public void delete(Player player) throws DataAccessException {
		String name = player.getName();
		try {
			Connection connection = super.getConnection();
			try {
				PreparedStatement stmt = connection
						.prepareStatement("DELETE FROM player WHERE name=?");
				try {
					stmt.setString(1, name);
					stmt.executeUpdate();
				} finally {
					stmt.close();
				}
			} finally {
				connection.close();
			}
		} catch (SQLException e) {
			throw new DataAccessException("Failed to delete player by name: "
					+ name, e);
		}

	}

	@Override
	public List<Player> getAll() throws DataAccessException {
		try {
			Connection connection = super.getConnection();
			try {
				Statement stmt = connection.createStatement();
				try {
					ResultSet rs = stmt.executeQuery("SELECT * FROM player");
					List<Player> playerList = new ArrayList<Player>();
					while (rs.next()) {
						playerList.add(this.loadFromRow(rs));
					}
					return playerList;
				} finally {
					stmt.close();
				}
			} finally {
				connection.close();
			}
		} catch (SQLException e) {
			throw new DataAccessException("Failed to get all players", e);
		}
	}

	@Override
	public Player getByName(String name) throws DataAccessException {
		try {
			Connection connection = super.getConnection();
			try {
				PreparedStatement stmt = connection
						.prepareStatement("SELECT * FROM player WHERE name LIKE ?");
				try {
					stmt.setString(1, name);
					ResultSet rs = stmt.executeQuery();
					return rs.next() ? this.loadFromRow(rs) : null;
				} finally {
					stmt.close();
				}
			} finally {
				connection.close();
			}
		} catch (SQLException e) {
			throw new DataAccessException("Failed to get player by name: "
					+ name, e);
		}
	}

	@Override
	public void save(Player player) throws DataAccessException {
		synchronized (player) {
			try {
				Connection connection = super.getConnection();
				try {
					PreparedStatement stmt = connection
						.prepareStatement("INSERT INTO player (name) VALUES (?)");
					try {
						stmt.setString(1, player.getName());
						stmt.executeUpdate();
					} finally {
						stmt.close();
					}
				} finally {
					connection.close();
				}
			} catch (SQLException e) {
				String msg = e.getMessage();
				if (msg != null && msg.contains("Duplicate")) {
					throw new DuplicateIdException(player.getName(), e);
				}
				throw new DataAccessException("Failed to create: " + player, e);
			}
		}
	}

	@Override
	public void update(Player player) throws DataAccessException {
		synchronized (player) {
			try {
				Connection connection = super.getConnection();
				try {
					PreparedStatement stmt = connection
						.prepareStatement("UPDATE player SET seasons=? WHERE name = ?");
					try {
						stmt.setInt(1, player.getSeasons());
						stmt.setString(2, player.getName());
						stmt.executeUpdate();
					} finally {
						stmt.close();
					}
				} finally {
					connection.close();
				}
			} catch (SQLException e) {
				String msg = e.getMessage();
				if (msg != null && msg.contains("Duplicate")) {
					throw new DuplicateIdException(player.getName(), e);
				}
				throw new DataAccessException("Failed to create: " + player, e);
			}
		}
	}

	private Player loadFromRow(ResultSet row) throws SQLException {
		Player player = new Player(row.getString(1), row.getInt(2));
		return player;
	}
}
