package somiba.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import somiba.domain.Mapping;


public class MySqlMappingDao extends AbstractDatabaseDao implements MappingDao {

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

	@Override
	public Mapping getByOriginal(String original) throws DataAccessException {
		return getWithString(original, "original");
	}

	@Override
	public Mapping getByCustom(String custom) throws DataAccessException {
		return getWithString(custom, "custom");
	}

	private Mapping getWithString(String value, String fieldName) throws DataAccessException {
		try {
			Connection connection = super.getConnection();
			try {
				PreparedStatement stmt = connection
						.prepareStatement("SELECT * FROM mapping WHERE " + fieldName + " LIKE ?");
				try {
					stmt.setString(1, value);
					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 mapping for " + value, e);
		}
	}

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

	private Mapping loadFromRow(ResultSet row) throws SQLException {
		Mapping mapping = new Mapping(row.getString(1), row.getString(2));
		return mapping;
	}
}
