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

import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.json.JsonObject;

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.AuthenticationContentEntity;
import com.scytl.products.ov.au.services.domain.model.authentication.AuthenticationContentRepository;
import com.scytl.products.ov.au.services.infrastructure.log.AuthenticationLogConstants;
import com.scytl.products.ov.au.services.infrastructure.log.AuthenticationLogEvents;
import com.scytl.products.ov.commons.beans.domain.model.authentication.AuthenticationContent;
import com.scytl.products.ov.commons.beans.exceptions.ResourceNotFoundException;
import com.scytl.products.ov.commons.logging.service.I18nLoggerMessages;
import com.scytl.products.ov.commons.tracking.TrackIdInstance;
import com.scytl.products.ov.commons.util.JsonUtils;

/**
 * Service which retrieves the Authentication Content.
 */
@Stateless
public class AuthenticationContentService {

    private static final I18nLoggerMessages I18N = I18nLoggerMessages.getInstance();
    // The Constant KEYSTORE.
    private static final String KEYSTORE = "authenticationTokenSignerKeystore"; //$NON-NLS-1$
    // The Constant CHALLENGE_LENGTH.
    private static final String CHALLENGE_LENGTH = "challengeLength"; //$NON-NLS-1$
    // The Constant TOKEN_EXPIRATION_TIME.
    private static final String TOKEN_EXPIRATION_TIME = "authTokenExpTime"; //$NON-NLS-1$
    // The Constant CHALLENGE_EXPIRATION_TIME.
    private static final String CHALLENGE_EXPIRATION_TIME = "challengeResExpTime"; //$NON-NLS-1$
    // The password for the authentication signature keystore.
    private static final String KEYSTORE_PW = "authenticationTokenSignerPassword";
    // The Constant PARAMS.
    private static final String PARAMS = "authenticationParams"; //$NON-NLS-1$
    
    private static final Logger LOG = LoggerFactory.getLogger("std");
    
    // The authentication content repository.    
    @Inject
    private AuthenticationContentRepository authenticationContentRepository;

    @Inject
    private SecureLoggingWriter secureLoggerWriter;

    @Inject
    private TrackIdInstance trackId;

    /**
     * Returns the AuthenticationContent for a given tenant and election event.
     *
     * @param tenantId - the tenant identifier.
     * @param electionEventId - the election event identifier.
     * @return An AuthenticationContent with the keystore and authentication parameters.
     * @throws ResourceNotFoundException if the authentication content is not found.
     */
    public AuthenticationContent getAuthenticationContent(String tenantId, String electionEventId)
        throws ResourceNotFoundException {

        LOG.info(
            I18N.getMessage("AuthenticationContentService.getAuthenticationContent.recoveringAuthContent"), tenantId, //$NON-NLS-1$
            electionEventId);

        AuthenticationContentEntity authenticationContentEntity;
        try {
            // recover from db
            authenticationContentEntity =
                authenticationContentRepository.findByTenantIdElectionEventId(tenantId, electionEventId);
        } catch (ResourceNotFoundException ex) {
            secureLoggerWriter.log(Level.INFO,
                new LogContent.LogContentBuilder().logEvent(AuthenticationLogEvents.AUTH_CONTENT_NOT_FOUND)
                    .electionEvent(electionEventId)
                    .additionalInfo(AuthenticationLogConstants.INFO_TRACK_ID, trackId.getTrackId())
                    .createLogInfo());
            throw ex;
        }
        // convert to json object
        JsonObject object = JsonUtils.getJsonObject(authenticationContentEntity.getJson());
        JsonObject params = object.getJsonObject(PARAMS);

        // create authentication content
        AuthenticationContent result = new AuthenticationContent();
        result.setChallengeExpirationTime(Integer.parseInt(params.getString(CHALLENGE_EXPIRATION_TIME)));
        result.setTokenExpirationTime(Integer.parseInt(params.getString(TOKEN_EXPIRATION_TIME)));
        result.setChallengeLength(Integer.parseInt(params.getString(CHALLENGE_LENGTH)));
        result.setPassword(object.getString(KEYSTORE_PW));
        String keyStore = new String(Base64.decodeBase64(object.getString(KEYSTORE)));
        result.setKeystore(JsonUtils.getJsonObject(keyStore));

        LOG.info(
            I18N.getMessage("AuthenticationContentService.getAuthenticationContent.authContentFound"), tenantId, electionEventId); //$NON-NLS-1$

        secureLoggerWriter.log(Level.INFO,
            new LogContent.LogContentBuilder().logEvent(AuthenticationLogEvents.AUTH_CONTENT_FOUND)
                .electionEvent(electionEventId)
                .additionalInfo(AuthenticationLogConstants.INFO_TRACK_ID, trackId.getTrackId())
                .createLogInfo());
        return result;
    }
}
