package ru.yandex.wmtools.common.util;

import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import ru.yandex.common.framework.pager.Pager;
import ru.yandex.common.util.db.OrderByClause;
import ru.yandex.wmtools.common.data.partition.IPartition;
import ru.yandex.wmtools.common.error.InternalException;

import java.util.Date;
import java.util.List;
import java.util.NavigableMap;

/**
 * User: baton
 * Date: 11.10.2007
 * Time: 18:06:46
 */
public class PartitionJdbcTemplate implements IServiceJdbcTemplate {
    private final IServiceJdbcTemplate[] jdbcTemplate;
    private final int databaseCount;

    private final IPartition partition;

    public PartitionJdbcTemplate(IServiceJdbcTemplate[] jdbcTemplate, IPartition partition) {
        this.jdbcTemplate = jdbcTemplate;
        this.databaseCount = jdbcTemplate.length;

        this.partition = partition;
    }

    @Override
    public JdbcOperations getJdbcOperations() throws InternalException {
        return jdbcTemplate[partition.getDatabaseIndex(databaseCount)].getJdbcOperations();
    }

    @Override
    public int queryForInt(final String sqlString, final Object... requestParams) throws InternalException {
        return jdbcTemplate[partition.getDatabaseIndex(databaseCount)].queryForInt(partition.getReadySqlString(sqlString), requestParams);
    }

    @Override
    public long queryForLong(final String sqlString, final Object... requestParams) throws InternalException {
        return jdbcTemplate[partition.getDatabaseIndex(databaseCount)].queryForLong(partition.getReadySqlString(sqlString), requestParams);
    }

    @Override
    public <T> T queryForObject(final String sqlString, final Class<T> aClass, final Object... requestParams) throws InternalException {
        return jdbcTemplate[partition.getDatabaseIndex(databaseCount)].queryForObject(partition.getReadySqlString(sqlString), aClass, requestParams);
    }

    @Override
    public <T> T queryForObject(final String sqlString, ParameterizedRowMapper<T> parameterizedRowMapper, final Object... requestParams) throws InternalException {
        return jdbcTemplate[partition.getDatabaseIndex(databaseCount)].queryForObject(partition.getReadySqlString(sqlString), parameterizedRowMapper, requestParams);
    }

    @Override
    public <T> java.util.List<T> query(final String sqlString, ParameterizedRowMapper<T> parameterizedRowMapper, final Object... requestParams) throws InternalException {
        return jdbcTemplate[partition.getDatabaseIndex(databaseCount)].query(partition.getReadySqlString(sqlString), parameterizedRowMapper, requestParams);
    }

    @Override
    public java.util.Map<String, Object> queryForMap(final String sqlString, final Object... requestParams) throws InternalException {
        return jdbcTemplate[partition.getDatabaseIndex(databaseCount)].queryForMap(partition.getReadySqlString(sqlString), requestParams);
    }

    @Override
    public java.util.List<java.util.Map<String, Object>> queryForList(final String sqlString, final Object... requestParams) throws InternalException {
        return jdbcTemplate[partition.getDatabaseIndex(databaseCount)].queryForList(partition.getReadySqlString(sqlString), requestParams);
    }

    @Override
    public int update(final String sqlString, final Object... requestParams) throws InternalException {
        return jdbcTemplate[partition.getDatabaseIndex(databaseCount)].update(partition.getReadySqlString(sqlString), requestParams);
    }

    @Override
    public Number insertSingle(String sqlString, Object... requestParams) throws InternalException {
        return jdbcTemplate[partition.getDatabaseIndex(databaseCount)].insertSingle(partition.getReadySqlString(sqlString), requestParams);
    }

    @Override
    public Date safeQueryForTimestamp(final String sqlString, final Object... requestParams) throws InternalException {
        return jdbcTemplate[partition.getDatabaseIndex(databaseCount)].safeQueryForTimestamp(partition.getReadySqlString(sqlString), requestParams);
    }

    @Override
    public Integer safeQueryForInt(final String sqlString, final Object... requestParams) throws InternalException {
        return jdbcTemplate[partition.getDatabaseIndex(databaseCount)].safeQueryForInt(partition.getReadySqlString(sqlString), requestParams);
    }

    @Override
    public Long safeQueryForLong(final String sqlString, final Object... requestParams) throws InternalException {
        return jdbcTemplate[partition.getDatabaseIndex(databaseCount)].safeQueryForLong(partition.getReadySqlString(sqlString), requestParams);
    }

    @Override
    public String safeQueryForString(final String sqlString, final Object... requestParams) throws InternalException {
        return jdbcTemplate[partition.getDatabaseIndex(databaseCount)].safeQueryForString(partition.getReadySqlString(sqlString), requestParams);
    }

    @Override
    public <E> E safeQueryForObject(final String sqlString, ParameterizedRowMapper<E> parameterizedRowMapper, final Object... requestParams) throws InternalException {
        return jdbcTemplate[partition.getDatabaseIndex(databaseCount)].safeQueryForObject(partition.getReadySqlString(sqlString), parameterizedRowMapper, requestParams);
    }

    @Override
    public <K, V> NavigableMap<K, V> queryForNavigableMap(final String sqlString, ParameterizedMapRowMapper<K, V> parameterizedRowMapper, Object... requestParams) throws InternalException {
        return jdbcTemplate[partition.getDatabaseIndex(databaseCount)].queryForNavigableMap(partition.getReadySqlString(sqlString), parameterizedRowMapper, requestParams);
    }

    @Override
    public void query(final String sqlString, final RowCallbackHandler rch, final Object... requestParams) throws InternalException {
        jdbcTemplate[partition.getDatabaseIndex(databaseCount)].query(partition.getReadySqlString(sqlString), rch, requestParams);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public <T> List<T> select(final String countSql, final String selectSql, final ParameterizedRowMapper<T> mapper, final OrderByClause order, final Pager pager, final Object... params) throws InternalException {
        return jdbcTemplate[partition.getDatabaseIndex(databaseCount)].select(partition.getReadySqlString(countSql), partition.getReadySqlString(selectSql), mapper, order, pager, params);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public <T> List<T> pageableSelect(final String countSql, final String selectSql, final ParameterizedRowMapper<T> mapper, final Pager pager, final Object... params) throws InternalException {
        return jdbcTemplate[partition.getDatabaseIndex(databaseCount)].pageableSelect(partition.getReadySqlString(countSql), partition.getReadySqlString(selectSql), mapper, pager, params);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public <T> List<T> orderableSelect(final String selectSql, final ParameterizedRowMapper<T> mapper, final OrderByClause order, final Object... params) throws InternalException {
        return jdbcTemplate[partition.getDatabaseIndex(databaseCount)].orderableSelect(partition.getReadySqlString(selectSql), mapper, order, params);
    }
}
