package jp.sf.amateras.mirage.type;

import java.math.BigDecimal;
import java.sql.Blob;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Date;

import jp.sf.amateras.mirage.util.IOUtil;

public class DefaultValueType implements ValueType {

	@Override
	public Object get(Class<?> type, ResultSet rs, int columnIndex) throws SQLException {
		if(type == String.class){
			return rs.getString(columnIndex);

		} else if(type == Integer.class || type == Integer.TYPE){
			return rs.getInt(columnIndex);

		} else if(type == Long.class  || type == Long.TYPE){
			return rs.getLong(columnIndex);

		} else if(type == Short.class  || type == Short.TYPE){
			return rs.getShort(columnIndex);

		} else if(type == Double.class  || type == Double.TYPE){
			return rs.getDouble(columnIndex);

		} else if(type == Float.class  || type == Float.TYPE){
			return rs.getFloat(columnIndex);

		} else if(type == Boolean.class  || type == Boolean.TYPE){
			return rs.getBoolean(columnIndex);

		} else if(type == BigDecimal.class){
			return rs.getBigDecimal(columnIndex);

		} else if(type == java.sql.Date.class){
			return rs.getDate(columnIndex);

		} else if(type == Date.class){
			return new Date(rs.getTimestamp(columnIndex).getTime());

		} else if(type == Time.class){
			return rs.getTime(columnIndex);

		} else if(type == Timestamp.class){
			return rs.getTimestamp(columnIndex);

		} else if(type.isArray() && type.getComponentType() == Byte.TYPE){
			Blob blob = rs.getBlob(columnIndex);
			return IOUtil.readStream(blob.getBinaryStream());
		}

		throw new RuntimeException("Unsupported type: " + type.getName());
	}

	@Override
	public Object get(Class<?> type, ResultSet rs, String columnName) throws SQLException {
		if(type == String.class){
			return rs.getString(columnName);

		} else if(type == Integer.class || type == Integer.TYPE){
			return rs.getInt(columnName);

		} else if(type == Long.class  || type == Long.TYPE){
			return rs.getLong(columnName);

		} else if(type == Short.class  || type == Short.TYPE){
			return rs.getShort(columnName);

		} else if(type == Double.class  || type == Double.TYPE){
			return rs.getDouble(columnName);

		} else if(type == Float.class  || type == Float.TYPE){
			return rs.getFloat(columnName);

		} else if(type == Boolean.class  || type == Boolean.TYPE){
			return rs.getBoolean(columnName);

		} else if(type == BigDecimal.class){
			return rs.getBigDecimal(columnName);

		} else if(type == java.sql.Date.class){
			return rs.getDate(columnName);

		} else if(type == Date.class){
			return new Date(rs.getTimestamp(columnName).getTime());

		} else if(type == Time.class){
			return rs.getTime(columnName);

		} else if( type == Timestamp.class){
			return rs.getTimestamp(columnName);

		} else if(type.isArray() && type.getComponentType() == Byte.TYPE){
			Blob blob = rs.getBlob(columnName);
			return IOUtil.readStream(blob.getBinaryStream());
		}

		throw new RuntimeException("Unsupported type: " + type.getName());
	}


	@Override
	public void set(Class<?> type, PreparedStatement stmt, Object value,
			int index) throws SQLException {
		if(type == String.class){
			stmt.setString(index, (String) value);

		} else if(type == Integer.class || type == Integer.TYPE){
			stmt.setInt(index, (Integer) value);

		} else if(type == Long.class  || type == Long.TYPE){
			stmt.setLong(index, (Long) value);

		} else if(type == Short.class  || type == Short.TYPE){
			stmt.setShort(index, (Short) value);

		} else if(type == Double.class  || type == Double.TYPE){
			stmt.setDouble(index, (Double) value);

		} else if(type == Float.class  || type == Float.TYPE){
			stmt.setFloat(index, (Float) value);

		} else if(type == Boolean.class  || type == Boolean.TYPE){
			stmt.setBoolean(index, (Boolean) value);

		} else if(type == BigDecimal.class){
			stmt.setBigDecimal(index, (BigDecimal) value);

		} else if(type == java.sql.Date.class){
			stmt.setDate(index, (java.sql.Date) value);

		} else if(type == Date.class){
			stmt.setTimestamp(index, new Timestamp(((Date) value).getTime()));

		} else if(type == Time.class){
			stmt.setTime(index, (Time) value);

		} else if(type == Timestamp.class){
			stmt.setTimestamp(index, (Timestamp) value);

		} else if(type.isArray() && type.getComponentType() == Byte.TYPE){
			Blob blob = stmt.getConnection().createBlob();
			blob.setBytes(0, (byte[]) value);
			stmt.setBlob(index, blob);

		} else {
			throw new RuntimeException("Unsupported type: " + type.getName());
		}
	}

	@Override
	public boolean isSupport(Class<?> type) {
		if(type == String.class
				|| type == Integer.class || type == Integer.TYPE
				|| type == Long.class  || type == Long.TYPE
				|| type == Short.class  || type == Short.TYPE
				|| type == Double.class  || type == Double.TYPE
				|| type == Float.class  || type == Float.TYPE
				|| type == Boolean.class  || type == Boolean.TYPE
				|| type == BigDecimal.class
				|| type == Date.class
				|| type == Time.class
				|| type == Timestamp.class
				|| type.isArray() && type.getComponentType() == Byte.TYPE){
			return true;
		}
		return false;
	}

}
