package ru.yandex.wmconsole.service;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.sql.Types;

import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.jdbc.support.GeneratedKeyHolder;

import ru.yandex.wmconsole.data.HostStatusChangedNotificationInfo;
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;

/**
 * @author Alexey Zakharov
 */
public class HostStatusChangedService extends AbstractDbService implements GroupableByHostService<HostStatusChangedNotificationInfo> {
    private static final String INSERT_HOST_STATUS_CHANGED_QUERY =
            "INSERT INTO " +
                        "tbl_notification_hoststatus (host_id, status, spider_ip, last_access) " +
                    "VALUES (?, ?, ?, ?)";

    private static final String SELECT_HOST_STATUS_CHANGED_QUERY =
            "SELECT " +
                        "host_id, status, spider_ip, last_access " +
                    "FROM " +
                        "tbl_notification_hoststatus " +
                    "WHERE " +
                        "issue_id = ?";

    private static final ParameterizedRowMapper<HostStatusChangedNotificationInfo> HOST_STATUS_CHANGED_MAPPER =
            new ParameterizedRowMapper<HostStatusChangedNotificationInfo>() {
                private static final String FIELD_HOST_ID = "host_id";
                private static final String FIELD_STATUS = "status";
                private static final String FIELD_SPIDER_IP = "spider_ip";
                private static final String FIELD_LAST_ACCESS = "last_access";

                @Override
                public HostStatusChangedNotificationInfo mapRow(ResultSet resultSet, int rowNum) throws SQLException {
                    final long hostId = resultSet.getLong(FIELD_HOST_ID);
                    final int status = resultSet.getInt(FIELD_STATUS);
                    final String spiderIp = resultSet.getString(FIELD_SPIDER_IP);
                    final java.util.Date lastAccess = SqlUtil.safeGetTimestamp(resultSet, FIELD_LAST_ACCESS);

                    return new HostStatusChangedNotificationInfo(hostId, status, spiderIp, lastAccess);
                }
            };

    public Long addHostStatusChanged(final Long hostId, final int status, final String spiderIp, final java.util.Date lastAccess)
            throws InternalException {
        GeneratedKeyHolder generatedKeyHolder = new GeneratedKeyHolder();
        PreparedStatementCreator psc = new PreparedStatementCreator() {
            @Override
            public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
                PreparedStatement ps = connection.prepareStatement(INSERT_HOST_STATUS_CHANGED_QUERY,
                        Statement.RETURN_GENERATED_KEYS);
                ps.setLong(1, hostId);
                ps.setInt(2, status);
                if (spiderIp != null) {
                    ps.setString(3, spiderIp);
                } else {
                    ps.setNull(3, Types.VARCHAR);
                }
                if (lastAccess != null) {
                    ps.setTimestamp(4, new Timestamp(lastAccess.getTime()));
                }  else {
                    ps.setNull(4, Types.TIMESTAMP);
                }
                return ps;
            }
        };

        getJdbcTemplate(WMCPartition.nullPartition()).getJdbcOperations().update(psc, generatedKeyHolder);
        return generatedKeyHolder.getKey().longValue();
    }

    public HostStatusChangedNotificationInfo getHostStatusChanged(Long issueId) throws InternalException {
        return getJdbcTemplate(WMCPartition.nullPartition()).queryForObject(
                SELECT_HOST_STATUS_CHANGED_QUERY,
                HOST_STATUS_CHANGED_MAPPER,
                issueId
        );
    }

    @Override
    public HostStatusChangedNotificationInfo getSingleNotification(Long id) throws InternalException {
        return getHostStatusChanged(id);
    }
}
