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

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.au.services.domain.model.authentication.AuthenticationToken;
import com.scytl.products.ov.au.services.domain.model.validation.AuthenticationTokenValidation;
import com.scytl.products.ov.au.services.infrastructure.log.AuthenticationLogEvents;
import com.scytl.products.ov.au.services.infrastructure.log.SecureLoggerHelper;
import com.scytl.products.ov.commons.beans.exceptions.AuthTokenValidationException;
import com.scytl.products.ov.commons.beans.exceptions.ResourceNotFoundException;
import com.scytl.products.ov.commons.tracking.TrackIdInstance;
import com.scytl.products.ov.commons.validation.ValidationResult;
import org.apache.commons.lang3.exception.ExceptionUtils;

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

import static com.scytl.products.ov.au.services.infrastructure.log.AuthenticationLogConstants.INFO_AUTH_TOKEN_ID;
import static com.scytl.products.ov.au.services.infrastructure.log.AuthenticationLogConstants.INFO_ERR_DESC;
import static com.scytl.products.ov.au.services.infrastructure.log.AuthenticationLogConstants.INFO_TRACK_ID;
import static com.scytl.products.ov.au.services.infrastructure.log.AuthenticationLogConstants.TIMESTAMP_AT;

/**
 * Decorator for authentication token validation.
 */
@Decorator
public abstract class AuthenticationTokenExpirationTimeValidationDecorator implements AuthenticationTokenValidation {

	@Inject
	@Delegate
	private AuthenticationTokenExpirationTimeValidation authenticationTokenExpirationTimeValidation;

	@Inject
	private TrackIdInstance trackId;

	@Inject
	private SecureLoggingWriter secureLoggerWriter;

	@Inject
	private SecureLoggerHelper secureLoggerHelper;

	/**
	 * @see com.scytl.products.ov.au.services.domain.model.validation.AuthenticationTokenValidation#execute(java.lang.String,
	 *      java.lang.String, java.lang.String,
	 *      com.scytl.products.ov.au.services.domain.model.authentication.AuthenticationToken)
	 */
	@Override
	public ValidationResult execute(String tenantId, String electionEventId, String votingCardId,
									AuthenticationToken authenticationToken) throws ResourceNotFoundException {
		final ValidationResult result;
		try {
			 result = authenticationTokenExpirationTimeValidation.execute(tenantId, electionEventId, votingCardId,
				authenticationToken);
			 return result;
		}catch (AuthTokenValidationException e ){
			logAuthTokenError(electionEventId, votingCardId, authenticationToken,
					"Auth token expired. " + e.getMessage(), AuthenticationLogEvents.AUTH_TOKEN_EXPIRED);
			throw e;
		}catch (ResourceNotFoundException e) {
			final String message = "Auth token expiration rules fails. Authentication Content not found: "
					+ ExceptionUtils.getRootCauseMessage(e);
			logAuthTokenError(electionEventId, votingCardId, authenticationToken, message,
					AuthenticationLogEvents.AUTH_CONTENT_NOT_FOUND);
			throw e;
		}

	}

	private void logAuthTokenError(String electionEventId, String votingCardId, AuthenticationToken authenticationToken, String value,
			AuthenticationLogEvents authTokenEvent) {
		secureLoggerWriter
				.log(Level.ERROR, new LogContent.LogContentBuilder()
						.logEvent(authTokenEvent)
						.objectId(secureLoggerHelper.getAuthTokenHash(authenticationToken))
						.user(votingCardId)
						.electionEvent(electionEventId)
						.additionalInfo(INFO_TRACK_ID, trackId.getTrackId())
						.additionalInfo(INFO_AUTH_TOKEN_ID, 
						    secureLoggerHelper.getAuthTokenId(authenticationToken))
						.additionalInfo(INFO_ERR_DESC, value)
						.additionalInfo(TIMESTAMP_AT, 
						    secureLoggerHelper.getAuthTokenTimestamp(authenticationToken))
						.createLogInfo());
	}

}
