package ru.yandex.wmtools.common.service;

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

import javax.sql.DataSource;

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.error.ExtraTagInfo;
import ru.yandex.wmtools.common.error.ExtraTagNameEnum;
import ru.yandex.wmtools.common.error.InternalException;
import ru.yandex.wmtools.common.error.InternalProblem;
import ru.yandex.wmtools.common.util.IServiceJdbcTemplate;
import ru.yandex.wmtools.common.util.ParameterizedMapRowMapper;
import ru.yandex.wmtools.common.util.ReadOnlyServiceJdbcTemplate;

/**
 * User: baton
 * Date: 24.08.2007
 * Time: 13:54:38
 */
public class ReadOnlyReplicationJdbcTemplate implements IService, IServiceJdbcTemplate {
    private final SafeReplicationJdbcTemplate safeReplicationJdbcTemplate;
    private final IServiceJdbcTemplate notRepliactedJdbcTemplate;
    private final String databaseInfo;

    public ReadOnlyReplicationJdbcTemplate(IServiceJdbcTemplate notRepliactedJdbcTemplate,
            IServiceJdbcTemplate reserveJdbcTemplate, DataSource dataSource, String databaseInfo,
            DBBanner dbBanner)
    {
        this.notRepliactedJdbcTemplate = notRepliactedJdbcTemplate;
        this.safeReplicationJdbcTemplate = new SafeReplicationJdbcTemplate(
                new ReadOnlyServiceJdbcTemplate(dataSource, databaseInfo), reserveJdbcTemplate, dbBanner);
        this.databaseInfo = databaseInfo;
    }

    @Override
    public JdbcOperations getJdbcOperations() throws InternalException {
        if (safeReplicationJdbcTemplate.isMasterBanned()) {
            throw new InternalException(InternalProblem.MASTER_DB_BANNED, "Master DB is BANNED!",
                    new ExtraTagInfo(ExtraTagNameEnum.DB_INFO, databaseInfo));
        }
        return notRepliactedJdbcTemplate.getJdbcOperations();
    }

    @Override
    public int queryForInt(final String sqlString, final Object... requestParams) throws InternalException {
        return safeReplicationJdbcTemplate.queryForInt(sqlString, requestParams);
    }

    @Override
    public long queryForLong(final String sqlString, final Object... requestParams) throws InternalException {
        return safeReplicationJdbcTemplate.queryForLong(sqlString, requestParams);
    }

    @Override
    public <T> T queryForObject(final String sqlString, Class<T> aClass, final Object... requestParams)
            throws InternalException
    {
        return safeReplicationJdbcTemplate.queryForObject(sqlString, aClass, requestParams);
    }

    @Override
    public <T> T queryForObject(final String sqlString, ParameterizedRowMapper<T> parameterizedRowMapper,
            final Object... requestParams) throws InternalException
    {
        return safeReplicationJdbcTemplate.queryForObject(sqlString, parameterizedRowMapper, requestParams);
    }

    @Override
    public <T> List<T> query(final String sqlString, ParameterizedRowMapper<T> parameterizedRowMapper,
            final Object... requestParams) throws InternalException
    {
        return safeReplicationJdbcTemplate.query(sqlString, parameterizedRowMapper, requestParams);
    }

    @Override
    public Map<String, Object> queryForMap(final String sqlString, final Object... requestParams)
            throws InternalException
    {
        return safeReplicationJdbcTemplate.queryForMap(sqlString, requestParams);
    }

    @Override
    public List<Map<String, Object>> queryForList(final String sqlString, final Object... requestParams)
            throws InternalException
    {
        return safeReplicationJdbcTemplate.queryForList(sqlString, requestParams);
    }

    @Override
    public int update(final String sqlString, final Object... requestParams) throws InternalException {
        if (safeReplicationJdbcTemplate.isMasterBanned()) {
            throw new InternalException(InternalProblem.MASTER_DB_BANNED, "Master DB is BANNED!",
                    new ExtraTagInfo(ExtraTagNameEnum.DB_INFO, databaseInfo));
        }
        return notRepliactedJdbcTemplate.update(sqlString, requestParams);
    }

    @Override
    public Number insertSingle(String sqlString, Object... requestParams) throws InternalException {
        if (safeReplicationJdbcTemplate.isMasterBanned()) {
            throw new InternalException(InternalProblem.MASTER_DB_BANNED, "Master DB is BANNED!",
                    new ExtraTagInfo(ExtraTagNameEnum.DB_INFO, databaseInfo));
        }
        return notRepliactedJdbcTemplate.insertSingle(sqlString, requestParams);
    }

    @Override
    public Date safeQueryForTimestamp(final String sqlString, final Object... requestParams) throws InternalException {
        return safeReplicationJdbcTemplate.safeQueryForTimestamp(sqlString, requestParams);
    }

    @Override
    public Integer safeQueryForInt(final String sqlString, final Object... requestParams) throws InternalException {
        return safeReplicationJdbcTemplate.safeQueryForInt(sqlString, requestParams);
    }

    @Override
    public Long safeQueryForLong(final String sqlString, final Object... requestParams) throws InternalException {
        return safeReplicationJdbcTemplate.safeQueryForLong(sqlString, requestParams);
    }

    @Override
    public String safeQueryForString(final String sqlString, final Object... requestParams) throws InternalException {
        return safeReplicationJdbcTemplate.safeQueryForString(sqlString, requestParams);
    }

    @Override
    public <E> E safeQueryForObject(final String sqlString, final ParameterizedRowMapper<E> parameterizedRowMapper,
            final Object... requestParams) throws InternalException
    {
        return safeReplicationJdbcTemplate.safeQueryForObject(sqlString, parameterizedRowMapper, requestParams);
    }

    @Override
    public <K, V> NavigableMap<K, V> queryForNavigableMap(final String sqlString,
            final ParameterizedMapRowMapper<K, V> parameterizedRowMapper, final Object... requestParams)
            throws InternalException
    {
        return safeReplicationJdbcTemplate.queryForNavigableMap(sqlString, parameterizedRowMapper, requestParams);
    }

    @Override
    public void query(final String sqlString, final RowCallbackHandler rch, final Object... requestParams)
            throws InternalException
    {
        safeReplicationJdbcTemplate.query(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 safeReplicationJdbcTemplate.select(countSql, 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 safeReplicationJdbcTemplate.pageableSelect(countSql, 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 safeReplicationJdbcTemplate.orderableSelect(selectSql, mapper, order, params);
    }
}
