package ru.yandex.webmaster3.storage.yql;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import ru.yandex.webmaster3.core.WebmasterException;
import ru.yandex.webmaster3.core.http.WebmasterErrorResponse;
import ru.yandex.webmaster3.core.util.functional.ThrowingConsumer;
import ru.yandex.webmaster3.core.util.functional.ThrowingFunction;

/**
 * @author akhazhoyan 08/2018
 */
public class YqlService {
    private static final Logger log = LoggerFactory.getLogger(YqlService.class);
    static {
        try {
            Class.forName("ru.yandex.yql.YqlDriver");
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    private final String yqlJdbcUrl;
    private final String yqlJdbcToken;

    @Autowired
    public YqlService(String yqlJdbcUrl, String yqlJdbcToken) {
        this.yqlJdbcUrl = yqlJdbcUrl;
        this.yqlJdbcToken = yqlJdbcToken;
    }

    public void execute(String query) {
        try (Connection connection = DriverManager.getConnection(yqlJdbcUrl, "unused", yqlJdbcToken);
             Statement statement = connection.createStatement()) {
            log.info("Running query: {}", String.valueOf(query).replace('\n', ' '));
            statement.execute(query);
        } catch (SQLException e) {
            throw new WebmasterException(e.getMessage(),
                    new WebmasterErrorResponse.YqlServiceErrorResponse(getClass(), e)
            );
        }
    }

    public <T, X extends Exception> void query(
            String query,
            ThrowingFunction<ResultSet, T, SQLException> mapper,
            ThrowingConsumer<T, X> f) throws X {
        log.info("Running query: {}", String.valueOf(query).replace('\n', ' '));
        try (Connection connection = DriverManager.getConnection(yqlJdbcUrl, "unused", yqlJdbcToken);
             Statement statement = connection.createStatement();
             ResultSet rs = statement.executeQuery(query)) {
            while (rs.next()) {
                f.accept(mapper.apply(rs));
            }
        } catch (SQLException e) {
            throw new WebmasterException(e.getMessage(), new WebmasterErrorResponse.YqlServiceErrorResponse(getClass(), e), e);
        }
    }
}
