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

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.nio.charset.StandardCharsets;
import java.security.PublicKey;
import java.util.Base64;

import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;

import com.scytl.cryptolib.api.asymmetric.AsymmetricServiceAPI;
import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.products.ov.commons.sign.SignatureMetadata;
import com.scytl.products.ov.commons.sign.beans.SignatureFieldsConstants;

/**
 * The Class MetadataFileVerifier.
 */
public class MetadataFileVerifier {

    /** The _signer. */
    private final AsymmetricServiceAPI verifier;

    /**
     * Instantiates a new metadata file verifier.
     *
     * @param verifier
     *            the verification service
     */
    public MetadataFileVerifier(final AsymmetricServiceAPI verifier) {
        this.verifier = verifier;
    }

    /**
     * Verify signature.
     *
     * @param publicKey
     *            the public key
     * @param metadataStream
     *            the metadata stream
     * @param sourceStream
     *            the source stream
     * @return true, if successful
     * @throws GeneralCryptoLibException
     *             if something goes wrong during the verification.
     */
    public boolean verifySignature(final PublicKey publicKey, final InputStream metadataStream,
            final InputStream sourceStream) throws GeneralCryptoLibException {

        try (JsonReader jsonReader = Json.createReader(metadataStream)) {
			final JsonObject metadataSignatureJson = jsonReader.readObject();
	        final SignatureMetadata signatureMetadata = SignatureMetadata.fromJsonObject(metadataSignatureJson);
	
	        StringBuilder sb = new StringBuilder();
	        signatureMetadata.getSignedFields().forEach((k, v) -> sb.append(v));
	        String fieldsString = sb.toString();
	
	        final byte[] bytes = fieldsString.getBytes(StandardCharsets.UTF_8);
	        InputStream bs = new ByteArrayInputStream(bytes);
	        InputStream seq = new SequenceInputStream(sourceStream, bs);
	
	        byte[] signatureBytes =
	            Base64.getDecoder().decode(metadataSignatureJson.getString(SignatureFieldsConstants.SIG_FIELD_SIGNATURE));
	        return verifier.verifySignature(signatureBytes, publicKey, seq);
        }
    }
}
