package ru.yandex.webmaster3.storage.util.sql;

import org.springframework.beans.factory.annotation.Required;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.core.RowMapper;
import ru.yandex.webmaster3.storage.WebmasterSQLException;
import ru.yandex.wmtools.common.util.ParameterizedMapRowMapper;

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

/**
 * @author avhaliullin
 */
public class ReadOnlyJdbcProvider implements JdbcProvider {
    private JdbcProvider delegate;

    private WebmasterSQLException.ReadOnly dbIsReadonly() {
        return new WebmasterSQLException.ReadOnly(delegate.getDbIdentity(), "Database " + getDbIdentity() + " is in read only state");
    }

    @Override
    public String getDbIdentity() {
        return delegate.getDbIdentity();
    }

    @Override
    public TransactionTemplate getTransactionTemplate() {
        return new TransactionTemplate() {
            @Override
            public <T> T execute(TransactionCallback<T> transaction) throws WebmasterSQLException {
                throw dbIsReadonly();
            }
        };
    }

    @Override
    public TransactionTemplate getLightTransactionTemplate() {
        return new TransactionTemplate() {
            @Override
            public <T> T execute(TransactionCallback<T> transaction) throws WebmasterSQLException {
                throw dbIsReadonly();
            }
        };
    }

    @Override
    public IReadJdbcTemplate getReadTemplate() {
        return delegate.getReadTemplate();
    }

    @Override
    public IWriteJdbcTemplate getWriteTemplate() {
        final IReadJdbcTemplate readTemplate = getReadTemplate();
        return new IWriteJdbcTemplate() {
            @Override
            public String getDbIdentity() {
                return readTemplate.getDbIdentity();
            }

            @Override
            public int update(String sqlString, Object... requestParams) throws WebmasterSQLException {
                throw dbIsReadonly();
            }

            @Override
            public Number insertSingle(String sqlString, Object... requestParams) throws WebmasterSQLException {
                throw dbIsReadonly();
            }

            public int queryForInt(String sqlString, Object... requestParams) throws WebmasterSQLException {
                return readTemplate.queryForInt(sqlString, requestParams);
            }

            public long queryForLong(String sqlString, Object... requestParams) throws WebmasterSQLException {
                return readTemplate.queryForLong(sqlString, requestParams);
            }

            public <T> T queryForObject(String sqlString, Class<T> aClass, Object... requestParams) throws WebmasterSQLException {
                return readTemplate.queryForObject(sqlString, aClass, requestParams);
            }

            public <T> T queryForObject(String sqlString, RowMapper<T> rowMapper, Object... requestParams) throws WebmasterSQLException {
                return readTemplate.queryForObject(sqlString, rowMapper, requestParams);
            }

            public <T> List<T> query(String sqlString, RowMapper<T> rowMapper, Object... requestParams) throws WebmasterSQLException {
                return readTemplate.query(sqlString, rowMapper, requestParams);
            }

            public Map<String, Object> queryForMap(String sqlString, Object... requestParams) throws WebmasterSQLException {
                return readTemplate.queryForMap(sqlString, requestParams);
            }

            public List<Map<String, Object>> queryForList(String sqlString, Object... requestParams) throws WebmasterSQLException {
                return readTemplate.queryForList(sqlString, requestParams);
            }

            public Date safeQueryForTimestamp(String sqlString, Object... requestParams) throws WebmasterSQLException {
                return readTemplate.safeQueryForTimestamp(sqlString, requestParams);
            }

            public Integer safeQueryForInt(String sqlString, Object... requestParams) throws WebmasterSQLException {
                return readTemplate.safeQueryForInt(sqlString, requestParams);
            }

            public Long safeQueryForLong(String sqlString, Object... requestParams) throws WebmasterSQLException {
                return readTemplate.safeQueryForLong(sqlString, requestParams);
            }

            public String safeQueryForString(String sqlString, Object... requestParams) throws WebmasterSQLException {
                return readTemplate.safeQueryForString(sqlString, requestParams);
            }

            public <E> E safeQueryForObject(String sqlString, RowMapper<E> rowMapper, Object... requestParams) throws WebmasterSQLException {
                return readTemplate.safeQueryForObject(sqlString, rowMapper, requestParams);
            }

            public <K, V> NavigableMap<K, V> queryForNavigableMap(String sqlString, ParameterizedMapRowMapper<K, V> parameterizedRowMapper, Object... requestParams) throws WebmasterSQLException {
                return readTemplate.queryForNavigableMap(sqlString, parameterizedRowMapper, requestParams);
            }

            public void query(String sqlString, RowCallbackHandler rch, Object... requestParams) throws WebmasterSQLException {
                readTemplate.query(sqlString, rch, requestParams);
            }
        };
    }

    @Required
    public void setDelegate(JdbcProvider delegate) {
        this.delegate = delegate;
    }
}
