/*
 * 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.ei.services.domain.model.rule;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

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

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.certificates.factory.CryptoX509Certificate;
import com.scytl.products.ov.commons.beans.domain.model.vote.Vote;
import com.scytl.products.ov.commons.domain.model.rule.AbstractRule;
import com.scytl.products.ov.commons.validation.ValidationError;
import com.scytl.products.ov.commons.beans.validation.ValidationErrorType;

/**
 * The Class implementing the rule for validating the credential id in the
 * certificate used for verify the signature.
 */
public class CredentialIdRule implements AbstractRule<Vote> {

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

    /**
     * return the rule name.
     *
     * @return the rule name.
     */
    // @Override
    @Override
    public String getName() {
        return RuleNames.VOTE_CREDENTIAL_ID.getText();
    }

    /**
     * Validates if the credential id is contained in the certificate used for
     * verify.
     *
     * @param vote
     *            The vote to which to apply the rule.
     * @return true, if successful.
     */
    @Override
    public ValidationError execute(Vote vote) {
        // validation result. By default is set to false
        ValidationError result = new ValidationError();
        result.setValidationErrorType(ValidationErrorType.FAILED);

        try {
            String certificateString = vote.getCertificate();
            // Obtain certificate
            InputStream inputStream = new ByteArrayInputStream(certificateString.getBytes(StandardCharsets.UTF_8));
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            X509Certificate certificate = (X509Certificate) cf.generateCertificate(inputStream);

            CryptoX509Certificate wrappedCertificate = new CryptoX509Certificate(certificate);
            String credentialToVerify = wrappedCertificate.getSubjectDn().getCommonName();

            if (credentialToVerify.contains(vote.getCredentialId())) {
                result.setValidationErrorType(ValidationErrorType.SUCCESS);
            }
        } catch (CertificateException | GeneralCryptoLibException e) {
            LOG.error("Error validating the credential id in the certificate", e);
        }
        return result;
    }
}
