/*
 * 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 javax.decorator.Decorator;
import javax.decorator.Delegate;
import javax.inject.Inject;
import java.io.IOException;

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.exceptions.DuplicateEntryException;
import com.scytl.products.ov.commons.beans.exceptions.EntryPersistenceException;
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.ballotbox.BallotBoxInformation;
import com.scytl.products.ov.ei.services.domain.model.ballotbox.BallotBoxInformationRepository;
import com.scytl.products.ov.ei.services.infrastructure.log.ElectionInformationLogConstants;
import com.scytl.products.ov.ei.services.infrastructure.log.ElectionInformationLogEvents;

/**
 * Decorator of the ballot box information repository.
 */
@Decorator
public abstract class BallotBoxInformationRepositoryDecorator implements BallotBoxInformationRepository {

    @Inject
    @Delegate
    private BallotBoxInformationRepository ballotBoxInformationRepository;

    @Inject
    private TrackIdInstance trackId;

    @Inject
    private SecureLoggingWriter secureLoggerWriter;

    @Override
    public BallotBoxInformation findByTenantIdElectionEventIdBallotBoxId(String tenantId, String electionEventId,
                                                                         String ballotBoxId) throws ResourceNotFoundException {
        try {
            BallotBoxInformation result = ballotBoxInformationRepository.findByTenantIdElectionEventIdBallotBoxId(tenantId,
                electionEventId, ballotBoxId);
            secureLoggerWriter.log(Level.INFO,
                new LogContent.LogContentBuilder().logEvent(ElectionInformationLogEvents.BALLOT_BOX_FOUND)
                    .objectId(ballotBoxId).user("").electionEvent(electionEventId)
                    .additionalInfo(ElectionInformationLogConstants.INFO_TRACK_ID, trackId.getTrackId())
                    .additionalInfo(ElectionInformationLogConstants.INFO_BALLOT_BOX_ID, ballotBoxId).createLogInfo());
            return result;
        } catch (ResourceNotFoundException e) {
            secureLoggerWriter.log(Level.ERROR,
                new LogContent.LogContentBuilder().logEvent(ElectionInformationLogEvents.BALLOT_BOX_NOT_FOUND)
                    .objectId(ballotBoxId).user("").electionEvent(electionEventId)
                    .additionalInfo(ElectionInformationLogConstants.INFO_TRACK_ID, trackId.getTrackId())
                    .additionalInfo(ElectionInformationLogConstants.INFO_BALLOT_BOX_ID, ballotBoxId)
                    .additionalInfo(ElectionInformationLogConstants.INFO_ERR_DESC,
                        "Resource not found in the BALLOT_BOX_INFORMATION table.")
                    .createLogInfo());
            throw e;
        }
    }

    @Override
    public void addBallotBoxInformation(String tenantId, String electionEventId, String ballotBoxId, String jsonContent)
        throws DuplicateEntryException, IOException {
        ballotBoxInformationRepository.addBallotBoxInformation(tenantId, electionEventId, ballotBoxId, jsonContent);
    }

    @Override
    public BallotBoxInformation save(final BallotBoxInformation ballotBoxInformation) throws DuplicateEntryException {
        try {
            final BallotBoxInformation saveBallotBoxInformation = ballotBoxInformationRepository.save(ballotBoxInformation);
            secureLoggerWriter.log(Level.INFO,
                new LogContent.LogContentBuilder().logEvent(ElectionInformationLogEvents.BALLOT_BOX_INFORMATION_SAVED)
                    .objectId(ballotBoxInformation.getBallotBoxId()).user("")
                    .electionEvent(ballotBoxInformation.getElectionEventId())
                    .additionalInfo(ElectionInformationLogConstants.INFO_TRACK_ID, trackId.getTrackId())
                    .additionalInfo(ElectionInformationLogConstants.INFO_BALLOT_BOX_ID,
                        ballotBoxInformation.getBallotBoxId())
                    .createLogInfo());
            return saveBallotBoxInformation;
        } catch (DuplicateEntryException ex) {
            secureLoggerWriter.log(Level.ERROR,
                new LogContent.LogContentBuilder().logEvent(ElectionInformationLogEvents.ERROR_SAVING_BALLOT_BOX_INFORMATION)
                    .objectId(ballotBoxInformation.getBallotBoxId()).user("")
                    .electionEvent(ballotBoxInformation.getElectionEventId())
                    .additionalInfo(ElectionInformationLogConstants.INFO_TRACK_ID, trackId.getTrackId())
                    .additionalInfo(ElectionInformationLogConstants.INFO_BALLOT_BOX_ID,
                        ballotBoxInformation.getBallotBoxId())
                    .additionalInfo(ElectionInformationLogConstants.INFO_ERR_DESC, ex.getMessage())
                    .createLogInfo());
            throw ex;
        }
    }
    
    @Override
    public BallotBoxInformation update(final BallotBoxInformation ballotBoxInformation) throws EntryPersistenceException {
        try {
            final BallotBoxInformation updateBallotBoxInformation = ballotBoxInformationRepository.update(ballotBoxInformation);
            secureLoggerWriter.log(Level.INFO,
                new LogContent.LogContentBuilder().logEvent(ElectionInformationLogEvents.BALLOT_BOX_INFORMATION_UPDATED)
                    .objectId(ballotBoxInformation.getBallotBoxId()).user("")
                    .electionEvent(ballotBoxInformation.getElectionEventId())
                    .additionalInfo(ElectionInformationLogConstants.INFO_TRACK_ID, trackId.getTrackId())
                    .additionalInfo(ElectionInformationLogConstants.INFO_BALLOT_BOX_ID,
                        ballotBoxInformation.getBallotBoxId())
                    .createLogInfo());
            return updateBallotBoxInformation;
        } catch (EntryPersistenceException ex) {
            secureLoggerWriter.log(Level.ERROR,
                new LogContent.LogContentBuilder().logEvent(ElectionInformationLogEvents.ERROR_UPDATING_BALLOT_BOX_INFORMATION)
                    .objectId(ballotBoxInformation.getBallotBoxId()).user("")
                    .electionEvent(ballotBoxInformation.getElectionEventId())
                    .additionalInfo(ElectionInformationLogConstants.INFO_TRACK_ID, trackId.getTrackId())
                    .additionalInfo(ElectionInformationLogConstants.INFO_BALLOT_BOX_ID,
                        ballotBoxInformation.getBallotBoxId())
                    .additionalInfo(ElectionInformationLogConstants.INFO_ERR_DESC, ex.getMessage())
                    .createLogInfo());
            throw ex;
        }
    }
}
