/*
 * 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.tallying.commons.io.writer;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.LinkedHashMap;

import javax.json.Json;
import javax.json.JsonWriter;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.products.ov.commons.sign.MetadataFileSigner;
import com.scytl.products.ov.commons.sign.SignatureMetadata;
import com.scytl.products.ov.commons.sign.beans.SignatureFieldsConstants;
import com.scytl.products.ov.tallying.command.TallyingHolder;

public class SignResultWriter {

    private static final String TALLYING_SERVICE_NAME = "tallying";

    private final MetadataFileSigner metadataFileSigner;

    public SignResultWriter(final MetadataFileSigner metadataFileSigner) {
        this.metadataFileSigner = metadataFileSigner;
    }

    public void signOutput(final Path originalFilePath, final TallyingHolder holder)
            throws IOException, GeneralCryptoLibException {

        LinkedHashMap<String, String> fields = extractFields(holder);

        final SignatureMetadata signature = metadataFileSigner.createSignature(holder.getSignatureKey(),
            Files.newInputStream(originalFilePath), fields);

        final Path metadataFilePath =
            Paths.get(originalFilePath.getParent().toString(), originalFilePath.getFileName() + ".metadata");

		try (OutputStream os = Files.newOutputStream(metadataFilePath, StandardOpenOption.CREATE);
				JsonWriter jsonWriter = Json.createWriter(os)) {

			jsonWriter.writeObject(signature.toJsonObject());
		}
    }

    private LinkedHashMap<String, String> extractFields(final TallyingHolder holder) {

        LinkedHashMap<String, String> fields = new LinkedHashMap<>();
        fields.put(SignatureFieldsConstants.SIG_FIELD_TENANTID, holder.getTenantId());
        fields.put(SignatureFieldsConstants.SIG_FIELD_EEVENTID, holder.getElectionEventId());
        fields.put(SignatureFieldsConstants.SIG_FIELD_BBOXID, holder.getBallotBoxId());
        fields.put(SignatureFieldsConstants.SIG_FIELD_TIMESTAMP, DateTimeFormatter.ISO_INSTANT.format(Instant.now()));
        fields.put(SignatureFieldsConstants.SIG_FIELD_COMPONENT, TALLYING_SERVICE_NAME);

        return fields;
    }
}
