package ru.yandex.wmconsole.service.dao;

import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.joda.time.DateTime;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;

import ru.yandex.common.util.db.DateRowMapper;
import ru.yandex.common.util.db.LongRowMapper;
import ru.yandex.wmconsole.data.HostRobotDbInfo;
import ru.yandex.wmconsole.data.UpdateStateEnum;
import ru.yandex.wmconsole.data.info.HostDbHostInfo;
import ru.yandex.wmconsole.data.info.RobotDbHostInfo;
import ru.yandex.wmconsole.data.info.UsersHostsInfo;
import ru.yandex.wmconsole.data.partition.WMCPartition;
import ru.yandex.wmtools.common.error.InternalException;
import ru.yandex.wmtools.common.service.AbstractDbService;
import ru.yandex.wmtools.common.util.SqlUtil;

/**
 * User: azakharov
 * Date: 31.05.13
 * Time: 17:42
 */
public class TblRobotdbInfoDao extends AbstractDbService {
    public HostRobotDbInfo getRobotDbInfo(HostDbHostInfo hostDbHostInfo) throws InternalException {
        String q =
                "SELECT" +
                "  state," +
                "  urls," +
                "  docs," +
                "  updated_on," +
                "  last_access," +
                "  shown_errors," +
                "  all_errors," +
                "  index_count," +
                "  banned_count," +
                "  internal_links_count," +
                "  links_count," +
                "  last_loader_time," +
                "  urls_trend," +
                "  index_count_trend," +
                "  tcy_trend," +
                "  links_count_trend," +
                "  htarc_in_index," +
                "  prev_in_index" +
                " FROM tbl_robotdb_info" +
                " WHERE host_id = ?";
        List<HostRobotDbInfo> result = getJdbcTemplate(new WMCPartition(hostDbHostInfo, null)).query(
                q, getMapper(), hostDbHostInfo.getHostDbHostId());
        return result.isEmpty() ? null : result.iterator().next();
    }

    public java.util.Date getUpdatedOn(HostDbHostInfo hostDbHostInfo) throws InternalException {
        final String query = "SELECT updated_on FROM tbl_robotdb_info WHERE host_id = ?";
        List<java.util.Date> res = getJdbcTemplate(new WMCPartition(hostDbHostInfo, null)).query(
                query, new DateRowMapper(), hostDbHostInfo.getHostDbHostId());
        return res.isEmpty() ? null : res.iterator().next();
    }

    public List<Long> getUrlsByStateAndUpdatedOn(UsersHostsInfo info, long hostDbHostId) throws InternalException {
        String q = "SELECT urls FROM tbl_robotdb_info WHERE host_id = ? " +
                " AND (updated_on < subtime(NOW(), \"1 00:00:00\") " +
                " OR state = " + UpdateStateEnum.WAITING.getValue() + ")"; // загрузить хост, который ранее был забанен

        return getJdbcTemplate(new WMCPartition(info.getHostId(), info.getHostName(), null))
                .query(q, new LongRowMapper(), hostDbHostId);
    }

    public Long getUrlsByHostId(HostDbHostInfo hostDbHostInfo) throws InternalException {
        String q = "SELECT urls FROM tbl_robotdb_info WHERE host_id = ? ";
        return getJdbcTemplate(new WMCPartition(hostDbHostInfo, null)).safeQueryForLong(q, hostDbHostInfo.getHostDbHostId());
    }

    public Integer getState(HostDbHostInfo hostDbHostInfo) throws InternalException {
        String q = "SELECT state FROM tbl_robotdb_info WHERE host_id = ? ";
        return getJdbcTemplate(new WMCPartition(hostDbHostInfo, null))
                .safeQueryForInt(q, hostDbHostInfo.getHostDbHostId());
    }

    public void increaseBannedCount(HostDbHostInfo hostDbHostInfo, long bannedCount) throws InternalException {
        getJdbcTemplate(new WMCPartition(hostDbHostInfo, null)).update(
                "UPDATE tbl_robotdb_info SET banned_count = IFNULL(banned_count + ?, ?) WHERE host_id = ?", bannedCount, bannedCount, hostDbHostInfo.getHostDbHostId());
    }

    public void updateBannedCount(HostDbHostInfo hostDbHostInfo, long bannedCount) throws InternalException {
        getJdbcTemplate(new WMCPartition(hostDbHostInfo, null)).update(
                "UPDATE tbl_robotdb_info SET banned_count = ? WHERE host_id = ?", bannedCount, hostDbHostInfo.getHostDbHostId());
    }

    public int addRobotDbInfo(HostDbHostInfo hostDbHostInfo, RobotDbHostInfo robotDbHostInfo,
            UpdateStateEnum state) throws InternalException
    {
        String q = "INSERT IGNORE INTO tbl_robotdb_info (host_id, urls, last_access, docs, state, updated_on) " +
                "VALUES (?, ?, ?, ?, ?, NOW())";

        return getJdbcTemplate(new WMCPartition(hostDbHostInfo, null)).update(q,
                hostDbHostInfo.getHostDbHostId(), robotDbHostInfo.getUrlsCount(), robotDbHostInfo.getLastAccess(),
                robotDbHostInfo.getDocsCount(), state.getValue());
    }

    public void updateState(HostDbHostInfo hostDbHostInfo, UpdateStateEnum state) throws InternalException {
        String q = "UPDATE tbl_robotdb_info SET state = ? WHERE host_id = ?";
        getJdbcTemplate(new WMCPartition(hostDbHostInfo, null)).update(q, state.getValue(), hostDbHostInfo.getHostDbHostId());
    }

    public void updateStateAndUpdatedOn(HostDbHostInfo hostInfo, UpdateStateEnum state) throws InternalException {
        String q = "UPDATE tbl_robotdb_info SET state = ?, updated_on = NOW() WHERE host_id = ?";
        getJdbcTemplate(new WMCPartition(hostInfo, null)).update(q, state.getValue(), hostInfo.getHostDbHostId());
    }

    public void updateStateToNew(int databaseId) throws InternalException {
        String q = "UPDATE tbl_robotdb_info SET state = ?, updated_on = NOW() WHERE state = ? AND updated_on < subtime(NOW(), \"3:00:00\") ";
        getJdbcTemplate(new WMCPartition(databaseId))
                .update(q, UpdateStateEnum.NEW.getValue(), UpdateStateEnum.FIRST_IN_PROGRESS.getValue());
    }

    private static ParameterizedRowMapper<HostRobotDbInfo> getMapper() {
        return new ParameterizedRowMapper<HostRobotDbInfo>() {
            @Override
            public HostRobotDbInfo mapRow(ResultSet rs, int rowNum) throws SQLException {
                UpdateStateEnum state = UpdateStateEnum.R.fromValueOrNull(rs.getInt("state"));
                int urls = rs.getInt("urls");
                int docs = rs.getInt("docs");
                Date updatedOn = rs.getDate("updated_on");
                Date lastAccess = rs.getDate("last_access");
                int shownErrors = rs.getInt("shown_errors");
                int allErrors = rs.getInt("all_errors");
                Integer indexCount = rs.getInt("index_count");
                if (rs.wasNull()) {
                    indexCount = null;
                }
                Integer bannedCount = SqlUtil.getIntNullable(rs, "banned_count");
                int internalLinksCount = rs.getInt("internal_links_count");
                Integer linksCount = rs.getInt("links_count");
                if (rs.wasNull()) {
                    linksCount = null;
                }
                int lastLoaderTime = rs.getInt("last_loader_time");
                int urlsTrend = rs.getInt("urls_trend");
                int indexCountTrend = rs.getInt("index_count_trend");
                int ticTrend = rs.getInt("tcy_trend");
                int linksCountTrend = rs.getInt("links_count_trend");
                boolean htarcInIndex = rs.getBoolean("htarc_in_index");
                boolean prevInIndex = rs.getBoolean("prev_in_index");

                return new HostRobotDbInfo(
                        state,
                        urls,
                        docs,
                        updatedOn != null ? new DateTime(updatedOn) : null,
                        lastAccess != null ? new DateTime(lastAccess) : null,
                        shownErrors,
                        allErrors,
                        indexCount,
                        bannedCount,
                        internalLinksCount,
                        linksCount,
                        lastLoaderTime,
                        urlsTrend,
                        indexCountTrend,
                        ticTrend,
                        linksCountTrend,
                        htarcInIndex,
                        prevInIndex
                );
            }
        };
    }
}
