/*
 * 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.domain.service;

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.ejb.EJBException;
import javax.inject.Inject;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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.ApplicationException;
import com.scytl.products.ov.commons.beans.exceptions.DuplicateEntryException;
import com.scytl.products.ov.commons.beans.exceptions.ResourceNotFoundException;
import com.scytl.products.ov.commons.logging.I18nLoggerMessages;
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.state.VotingCardState;
import com.scytl.products.ov.vw.services.domain.model.state.VotingCardStates;

/**
 * Decorator for voting card state service.
 */
@Decorator
public abstract class VotingCardStateServiceDecorator implements VotingCardStateService {

    private static final I18nLoggerMessages I18N = I18nLoggerMessages.getInstance();

    @Inject
    @Delegate
    private VotingCardStateService votingCardStateService;

    @Inject
    private SecureLoggingWriter secureLoggerWriter;

    private static final Logger LOG = LoggerFactory.getLogger("std");

    @Inject
    private TrackIdInstance trackId;

    @Inject
    private SecureLoggerInformation secureLoggerInformation;

    /**
     * @see com.scytl.products.ov.vw.services.domain.service.VotingCardStateService#getVotingCardState(java.lang.String,
     *      java.lang.String, java.lang.String)
     */
    @Override
    public VotingCardState getVotingCardState(String tenantId, String electionEventId, String votingCardId)
            throws ApplicationException {
        try {
            VotingCardState result = votingCardStateService.getVotingCardState(tenantId, electionEventId, votingCardId);

            secureLoggerWriter.log(INFO,
                new LogContent.LogContentBuilder().logEvent(VotingWorkflowLogEvents.VOTING_CARD_STATUS_FOUND)
                    .objectId(secureLoggerInformation.getAuthenticationTokenHash()).user(votingCardId)
                    .electionEvent(electionEventId)
                    .additionalInfo(VotingWorkflowLogConstants.INFO_TRACK_ID, trackId.getTrackId())
                    .additionalInfo(VotingWorkflowLogConstants.INFO_STATUS_VOTING_CARD, result.getState().name())
                    .createLogInfo());

            LOG.info(I18N.getMessage("VotingCardStateService.getVotingCardState.found"), tenantId, electionEventId,
                votingCardId, result.getState().name());
            return result;
        } catch (EJBException | ApplicationException e) {
            secureLoggerWriter.log(ERROR,
                new LogContent.LogContentBuilder().logEvent(VotingWorkflowLogEvents.VOTING_CARD_STATUS_NOT_FOUND)
                    .objectId(secureLoggerInformation.getAuthenticationTokenHash()).user(votingCardId)
                    .electionEvent(electionEventId)
                    .additionalInfo(VotingWorkflowLogConstants.INFO_TRACK_ID, trackId.getTrackId())
                    .additionalInfo(VotingWorkflowLogConstants.INFO_ERR_DESC,
                        "Error getting the voting card state: " + ExceptionUtils.getRootCauseMessage(e))
                    .createLogInfo());
            LOG.info(I18N.getMessage("VotingCardStateService.getVotingCardState.notFound"), tenantId, electionEventId,
                votingCardId);
            throw e;
        }
    }

    /**
     * @see com.scytl.products.ov.vw.services.domain.service.VotingCardStateService#updateVotingCardState(java.lang.String,
     *      java.lang.String, java.lang.String,
     *      com.scytl.products.ov.vw.services.domain.model.state.VotingCardStates)
     */
    @Override
    public void updateVotingCardState(String tenantId, String electionEventId, String votingCardId,
            VotingCardStates state) throws ResourceNotFoundException, ApplicationException, DuplicateEntryException {
        try {
            votingCardStateService.updateVotingCardState(tenantId, electionEventId, votingCardId, state);
            secureLoggerWriter.log(INFO,
                new LogContent.LogContentBuilder().logEvent(VotingWorkflowLogEvents.VOTING_CARD_STATUS_UPDATING_OK)
                    .objectId(secureLoggerInformation.getAuthenticationTokenHash()).user(votingCardId)
                    .electionEvent(electionEventId)
                    .additionalInfo(VotingWorkflowLogConstants.INFO_TRACK_ID, trackId.getTrackId())
                    .additionalInfo(VotingWorkflowLogConstants.INFO_STATUS_VOTING_CARD, state.name()).createLogInfo());
        } catch (EJBException | ResourceNotFoundException | ApplicationException
                | DuplicateEntryException e) {
            secureLoggerWriter.log(ERROR,
                new LogContent.LogContentBuilder().logEvent(VotingWorkflowLogEvents.VOTING_CARD_STATUS_UPDATING_ERROR)
                    .objectId(secureLoggerInformation.getAuthenticationTokenHash()).user(votingCardId)
                    .electionEvent(electionEventId)
                    .additionalInfo(VotingWorkflowLogConstants.INFO_TRACK_ID, trackId.getTrackId())
                    .additionalInfo(VotingWorkflowLogConstants.INFO_ERR_DESC,
                        "Error updating voting card state: " + ExceptionUtils.getRootCauseMessage(e))
                    .additionalInfo(VotingWorkflowLogConstants.INFO_STATUS_VOTING_CARD, state.name()).createLogInfo());
            throw e;
        }
    }

}
