/*
 * 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.cr.ui.ws.rs.operation;

import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.scytl.cryptolib.certificates.bean.X509CertificateType;
import com.scytl.products.oscore.logging.core.provider.TransactionInfoProvider;
import com.scytl.products.ov.commons.beans.domain.model.platform.PlatformInstallationData;
import com.scytl.products.ov.commons.beans.exceptions.DuplicateEntryException;
import com.scytl.products.ov.commons.beans.exceptions.ResourceNotFoundException;
import com.scytl.products.ov.commons.beans.validation.CertificateValidationService;
import com.scytl.products.ov.commons.beans.validation.CryptographicOperationException;
import com.scytl.products.ov.commons.domain.model.platform.PlatformInstallationDataHandler;
import com.scytl.products.ov.commons.logging.config.SecureLoggerInitializer;
import com.scytl.products.ov.commons.logging.domain.model.LoggingKeystoreRepository;
import com.scytl.products.ov.commons.util.HttpRequestService;
import com.scytl.products.ov.cr.services.domain.model.certificate.CertificateEntity;
import com.scytl.products.ov.cr.services.domain.model.certificate.CertificateRepository;
import com.scytl.products.ov.cr.services.domain.model.platform.CrCertificateValidationService;
import com.scytl.products.ov.cr.services.domain.model.platform.CrLoggingKeystoreEntity;
import com.scytl.products.ov.cr.services.domain.model.platform.CrLoggingKeystoreRepository;
import com.scytl.products.ov.cr.services.infrastructure.log.CrLoggingInitializationState;

/**
 * Endpoint for upload the information during the installation of the platform in the system
 */
@Path(CrPlatformDataResource.RESOURCE_PATH)
@Stateless(name = "cr-platformDataResource")
public class CrPlatformDataResource {

	public static final String RESOURCE_PATH = "platformdata";
	
    private static final Logger LOG = LoggerFactory.getLogger("std");

    private static final String CONTEXT = "CR";

    private static final String ENCRYPTION_PW_PROPERTIES_KEY = "CR_log_encryption";

    private static final String SIGNING_PW_PROPERTIES_KEY = "CR_log_signing";
    
    @Inject
    @CrLoggingKeystoreRepository
    LoggingKeystoreRepository loggingKeystoreRepository;

    @Inject
    CertificateRepository certificateRepository;

    @Inject
    CrLoggingInitializationState loggingInitializationState;

    @Inject
    @CrCertificateValidationService
    CertificateValidationService certificateValidationService;

    @Inject
    TransactionInfoProvider transactionInfoProvider;

    @Inject
    HttpRequestService httpRequestService;

    /**
     * Installs the logging keystores and platform CA in the service. Additionally, this method also attempts to
     * initialize the secure logging system.
     *
     * @param data
     *            all the platform data.
     * @return
     * @throws CryptographicOperationException
     * @throws DuplicateEntryException
     * @throws ResourceNotFoundException
     */

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response savePlatformData(final PlatformInstallationData data, @Context HttpServletRequest request)
            throws CryptographicOperationException, DuplicateEntryException, ResourceNotFoundException {

        transactionInfoProvider.generate("", httpRequestService.getIpClientAddress(request),
            httpRequestService.getIpServer(request));
        try {

            String platformName = PlatformInstallationDataHandler.savePlatformCertificateChain(data,
                certificateRepository, certificateValidationService, new CertificateEntity(), new CertificateEntity());

            String encryptionKey = data.getLoggingEncryptionKeystoreBase64();
            String signingKey = data.getLoggingSigningKeystoreBase64();

            CrLoggingKeystoreEntity encryptionKeystore = new CrLoggingKeystoreEntity();
            encryptionKeystore.setPlatformName(platformName);
            encryptionKeystore.setKeystoreContent(encryptionKey);
            encryptionKeystore.setKeyType(X509CertificateType.ENCRYPT.name());
            loggingKeystoreRepository.save(encryptionKeystore);
            LOG.info("CR - encryption keystore saved to DB");

            CrLoggingKeystoreEntity signingKeystore = new CrLoggingKeystoreEntity();
            signingKeystore.setPlatformName(platformName);
            signingKeystore.setKeystoreContent(signingKey);
            signingKeystore.setKeyType(X509CertificateType.SIGN.name());
            loggingKeystoreRepository.save(signingKeystore);
            LOG.info("CR - signing keystore saved to DB");

            SecureLoggerInitializer secureLoggerInitializer = new SecureLoggerInitializer(loggingInitializationState,
                loggingKeystoreRepository, CONTEXT, ENCRYPTION_PW_PROPERTIES_KEY, SIGNING_PW_PROPERTIES_KEY);

            secureLoggerInitializer.initializeFromUploadData(encryptionKey, signingKey);
            LOG.info("CR - logging initialized successfully");
            loggingInitializationState.setInitialized(true);

            return Response.ok().build();

        } catch (Exception e) {
            throw new IllegalStateException("CR - error while trying to initialize logging", e);
        }
    }
}
