/*
 * 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.ei.services.infrastructure.persistence;

import static com.scytl.products.oscore.logging.api.domain.Level.ERROR;
import static com.scytl.products.oscore.logging.api.domain.Level.INFO;

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

import com.scytl.products.ov.commons.logging.config.Audit;
import org.apache.commons.lang3.exception.ExceptionUtils;

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.exceptions.DuplicateEntryException;
import com.scytl.products.ov.commons.beans.exceptions.ResourceNotFoundException;
import com.scytl.products.ov.commons.tracking.TrackIdInstance;
import com.scytl.products.ov.ei.services.domain.model.castcode.VoteCastCode;
import com.scytl.products.ov.ei.services.domain.model.castcode.VoteCastCodeRepository;
import com.scytl.products.ov.ei.services.infrastructure.log.ElectionInformationLogConstants;
import com.scytl.products.ov.ei.services.infrastructure.log.ElectionInformationLogEvents;

/**
 * Decorator of the vote cast code repository.
 */
@Decorator
public abstract class VoteCastCodeRepositoryDecorator implements VoteCastCodeRepository {

	@Inject
	@Delegate
	private VoteCastCodeRepository voteCastCodeRepository;

	@Inject
	private TrackIdInstance trackId;

	@Inject
	private SecureLoggingWriter secureLoggerWriter;

	@Inject
	@Audit
	private SecureLoggingWriter auditLoggerWriter;

	/**
	 * @see com.scytl.products.ov.ei.services.domain.model.castcode.VoteCastCodeRepository#findByTenantIdElectionEventIdVotingCardId(java.lang.String,
	 *      java.lang.String, java.lang.String)
	 */
	@Override
	public VoteCastCode findByTenantIdElectionEventIdVotingCardId(String tenantId, String electionEventId,
			String votingCardId) throws ResourceNotFoundException {
		try {
			VoteCastCode result =
				voteCastCodeRepository.findByTenantIdElectionEventIdVotingCardId(tenantId, electionEventId, votingCardId);
			secureLoggerWriter.log(INFO,
				new LogContent.LogContentBuilder().logEvent(ElectionInformationLogEvents.VOTE_CAST_FOUND)
					.objectId(votingCardId).user(votingCardId).electionEvent(electionEventId)
					.additionalInfo(ElectionInformationLogConstants.INFO_TRACK_ID, trackId.getTrackId()).createLogInfo());
			return result;
		} catch (ResourceNotFoundException e) {
			secureLoggerWriter.log(ERROR,
				new LogContent.LogContentBuilder().logEvent(ElectionInformationLogEvents.VOTE_CAST_NOT_FOUND)
					.objectId(votingCardId).user(votingCardId).electionEvent(electionEventId)
					.additionalInfo(ElectionInformationLogConstants.INFO_TRACK_ID, trackId.getTrackId())
					.additionalInfo(ElectionInformationLogConstants.INFO_ERR_DESC,
						"Resource not found in the VOTE_CAST_CODE table.")
					.createLogInfo());
			throw e;
		}
	}

	/**
	 * @see com.scytl.products.ov.ei.services.domain.model.castcode.VoteCastCodeRepository#save(java.lang.String,
	 *      java.lang.String, java.lang.String, com.scytl.products.ov.ei.services.domain.model.castcode.VoteCastCode)
	 */
	@Override
	public void save(String tenantId, String electionEventId, String votingCardId, VoteCastCode voteCastCode)
			throws DuplicateEntryException {

		try {
			voteCastCodeRepository.save(tenantId, electionEventId, votingCardId, voteCastCode);
			LogContent saveLogInfo =
				new LogContent.LogContentBuilder().logEvent(ElectionInformationLogEvents.VOTE_CAST_CODE_SAVED)
					.objectId(votingCardId).user(votingCardId).electionEvent(electionEventId)
					.additionalInfo(ElectionInformationLogConstants.INFO_TRACK_ID, trackId.getTrackId()).createLogInfo();
			secureLoggerWriter.log(INFO, saveLogInfo);
			auditLoggerWriter.log(INFO, saveLogInfo);
		} catch (PersistenceException | DuplicateEntryException e) {
			LogContent errorSavingLogInfo =
				new LogContent.LogContentBuilder().logEvent(ElectionInformationLogEvents.ERROR_SAVING_VOTE_CAST_CODE)
					.objectId(votingCardId).user(votingCardId).electionEvent(electionEventId)
					.additionalInfo(ElectionInformationLogConstants.INFO_TRACK_ID, trackId.getTrackId())
					.additionalInfo(ElectionInformationLogConstants.INFO_ERR_DESC,
						"Error saving vote cast code: " + ExceptionUtils.getRootCauseMessage(e))
					.createLogInfo();
			secureLoggerWriter.log(ERROR, errorSavingLogInfo);
			auditLoggerWriter.log(ERROR, errorSavingLogInfo);
			throw e;
		}
	}

}
