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

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.security.cert.X509Certificate;

import org.springframework.stereotype.Service;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.primitives.primes.utils.PemUtils;
import com.scytl.products.ov.commons.path.PathResolver;
import com.scytl.products.ov.sdm.domain.service.ConfigConstants;

/**
 * Service responsible for the loading and storing root CA certificates, such as
 * the platform CA or the tenant CA.
 */
@Service
abstract class RootCAServiceImpl {
    private final PathResolver pathResolver;
    private String certificateName;

    public RootCAServiceImpl(PathResolver pathResolver, String certificateName) {
        this.pathResolver = pathResolver;
        this.certificateName = certificateName;
    }

    /**
     * Saves a given PlatformRoot CA certificate to the {@link #getCertificatePath()}
     * in PEM format.
     * 
     * @param certificate
     *            the certificate
     * @throws IOException
     *             I/O error occurred.
     */
    public void save(X509Certificate certificate) throws IOException {
        String pem;
        try {
            pem = PemUtils.certificateToPem(certificate);
        } catch (GeneralCryptoLibException e) {
            throw new IllegalArgumentException("Invalid certificate.", e);
        }
        byte[] bytes = pem.getBytes(StandardCharsets.UTF_8);
        Path file = getCertificatePath();
        Files.createDirectories(file.getParent());
        Files.write(file, bytes);
    }

    /**
     * Loads PlatformRoot CA certificate from the {@link #getCertificatePath()} in
     * PEM format.
     * 
     * @return the certificate
     * @throws NoSuchFileException
     *             the certificate does not exist
     * @throws IOException
     *             I/O error occurred.
     */
    public X509Certificate load() throws NoSuchFileException, IOException {
        byte[] pem = Files.readAllBytes(getCertificatePath());
        try {
            return (X509Certificate) PemUtils.certificateFromPem(new String(pem, StandardCharsets.UTF_8));
        } catch (GeneralCryptoLibException e) {
            throw new IllegalStateException("Invalid certificate file.", e);
        }
    }

    /**
     * Returns the configuration PEM file storing the PlatformRoot CA
     * certificate. It is not guaranteed that the returned file really exists.
     * 
     * @return the certificate file.
     */
    public Path getCertificatePath() {
        return pathResolver.resolve(ConfigConstants.CONFIG_FILES_BASE_DIR, certificateName);
    }
}
