/*
 * 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.vw.services.infrastructure.remote;

import java.io.IOException;

import javax.decorator.Decorator;
import javax.decorator.Delegate;
import javax.inject.Inject;

import org.apache.commons.lang3.exception.ExceptionUtils;

import com.scytl.products.oscore.logging.api.domain.Level;
import com.scytl.products.oscore.logging.api.domain.LogContent;
import com.scytl.products.oscore.logging.api.writer.SecureLoggingWriter;
import com.scytl.products.ov.commons.beans.domain.model.receipt.Receipt;
import com.scytl.products.ov.commons.beans.domain.model.vote.Vote;
import com.scytl.products.ov.commons.beans.exceptions.ApplicationException;
import com.scytl.products.ov.commons.beans.exceptions.ResourceNotFoundException;
import com.scytl.products.ov.commons.beans.exceptions.VoteRepositoryException;
import com.scytl.products.ov.commons.dto.VoteAndComputeResults;
import com.scytl.products.ov.commons.tracking.TrackIdInstance;
import com.scytl.products.ov.vw.infrastructure.log.SecureLoggerInformation;
import com.scytl.products.ov.vw.infrastructure.log.VotingWorkflowLogConstants;
import com.scytl.products.ov.vw.infrastructure.log.VotingWorkflowLogEvents;
import com.scytl.products.ov.vw.services.domain.model.vote.VoteRepository;

/**
 * Decorator of the vote repository.
 */
@Decorator
public abstract class VoteRepositoryDecorator implements VoteRepository {

    @Inject
    @Delegate
    private VoteRepository voteRepository;

    @Inject
    private TrackIdInstance trackId;

    @Inject
    private SecureLoggingWriter secureLoggerWriter;

    @Inject
    private SecureLoggerInformation secureLoggerInformation;

    /**
     * @see com.scytl.products.ov.vw.services.domain.model.vote.VoteRepository#save(String,
     *      String, Vote, String)
     */
    @Override
    public Receipt save(String tenantId, String electionEventId, VoteAndComputeResults vote,
            String authenticationTokenJsonString) throws ApplicationException, ResourceNotFoundException {
        try {
            Receipt receipt = voteRepository.save(tenantId, electionEventId, vote, authenticationTokenJsonString);
            secureLoggerWriter.log(Level.INFO,
                new LogContent.LogContentBuilder().logEvent(VotingWorkflowLogEvents.VOTE_STORING_OK)
                    .objectId(secureLoggerInformation.getAuthenticationTokenHash())
                    .user(vote.getVote().getVotingCardId()).electionEvent(vote.getVote().getElectionEventId())
                    .additionalInfo(VotingWorkflowLogConstants.INFO_TRACK_ID, trackId.getTrackId())
                    .additionalInfo(VotingWorkflowLogConstants.INFO_RECEIPT, receipt.getReceipt())
                    .additionalInfo(VotingWorkflowLogConstants.INFO_VOTE_HASH, secureLoggerInformation.getVoteHash())
                    .createLogInfo());
            return receipt;
        } catch (ApplicationException e) {
            secureLoggerWriter
                .log(Level.ERROR,
                    new LogContent.LogContentBuilder().logEvent(VotingWorkflowLogEvents.VOTE_STORING_ERROR)
                        .objectId(secureLoggerInformation.getAuthenticationTokenHash())
                        .user(vote.getVote().getVotingCardId()).electionEvent(vote.getVote().getElectionEventId())
                        .additionalInfo(VotingWorkflowLogConstants.INFO_TRACK_ID, trackId.getTrackId())
                        .additionalInfo(VotingWorkflowLogConstants.INFO_VOTE_HASH,
                            secureLoggerInformation.getVoteHash())
                        .additionalInfo(VotingWorkflowLogConstants.INFO_ERR_DESC,
                            "Error saving vote and receipt: " + ExceptionUtils.getRootCauseMessage(e))
                        .createLogInfo());
            throw e;
        }
    }

    /**
     * @throws VoteRepositoryException
     * @see com.scytl.products.ov.vw.services.domain.model.vote.VoteRepository#findByTenantIdElectionEventIdVotingCardId(java.lang.String,
     *      java.lang.String, java.lang.String)
     */
    @Override
    public VoteAndComputeResults findByTenantIdElectionEventIdVotingCardId(String tenantId, String electionEventId,
            String votingCardId) throws ResourceNotFoundException, VoteRepositoryException {
        return voteRepository.findByTenantIdElectionEventIdVotingCardId(tenantId, electionEventId, votingCardId);
    }

    @Override
    public boolean voteExists(final String tenantId, final String electionEventId, final String votingCardId)
            throws VoteRepositoryException {
        return voteRepository.voteExists(tenantId, electionEventId, votingCardId);
    }
}
