/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
package com.scytl.products.ov.channel.cc.choicecodes.verification.service;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLIntegrityConstraintViolationException;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;

@Repository
public class ComputedVerificationCardsRepositoryImpl implements ComputedVerificationCardsRepository {

    @Autowired
    @Qualifier("TransactionAware")
    private DataSource dataSource;

    @Override
    public void saveComputedVerificationCard(String electionEventId, String verificationCardId)
            throws ComputedVerificationCardExistsException {
        String sql = "insert into computed_verification_cards (election_event_id, verification_card_id) values (?,?) ";

        try (Connection connection = dataSource.getConnection();
                PreparedStatement statement = connection.prepareStatement(sql)) {
            statement.setString(1, electionEventId);
            statement.setString(2, verificationCardId);
            statement.executeUpdate();
        } catch (SQLIntegrityConstraintViolationException e) {
            throw new ComputedVerificationCardExistsException(
                "Existing computed verification card id entry " + verificationCardId + " eeId " + electionEventId, e);
        } catch (SQLException e) {
            throw new IllegalStateException("Failed trying to access computed verification cards table.", e);
        }
    }

    @Override
    public int getComputeVerificationCardVoteCastAttempts(String electionEventId, String verificationCardId)
            throws ComputedVerificationCardNotFoundException {
        String sql =
            "select cast_attempts from computed_verification_cards where election_event_id = ? and verification_card_id = ? ";
        try (Connection connection = dataSource.getConnection();
                PreparedStatement statement = connection.prepareStatement(sql)) {
            statement.setString(1, electionEventId);
            statement.setString(2, verificationCardId);
            ResultSet resultSet = statement.executeQuery();
            if (resultSet.next()) {
                return resultSet.getInt(1);
            } else {
                throw new ComputedVerificationCardNotFoundException(
                    "No existing computed verification card found by id " + verificationCardId + " eeId "
                        + electionEventId);
            }
        } catch (SQLException e) {
            throw new IllegalStateException("Failed trying to access computed verification cards table.", e);
        }
    }

    @Override
    public void updateComputedVerificationCardVoteCastAttempt(String electionEventId, String verificationCardId)
            throws ComputedVerificationCardNotFoundException {
        String sql =
            "update computed_verification_cards set cast_attempts = cast_attempts + 1 where election_event_id = ? and verification_card_id = ? ";
        try (Connection connection = dataSource.getConnection();
                PreparedStatement statement = connection.prepareStatement(sql)) {
            statement.setString(1, electionEventId);
            statement.setString(2, verificationCardId);
            int modified = statement.executeUpdate();

            if (modified == 0) {
                throw new ComputedVerificationCardNotFoundException(
                    "No existing computed verification card found by id " + verificationCardId + " eeId "
                        + electionEventId);
            }

        } catch (SQLException e) {
            throw new IllegalStateException("Failed trying to access computed verification cards table.", e);
        }
    }

}
