package com.sphereon.libs.blockchain.commons;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;

import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;


/**
 * Created by niels on 3-7-2017.
 */
public class Digest {
    public enum Algorithm {
        SHA_256("SHA-256"), SHA_512("SHA-512");
        private final String algorithm;

        Algorithm(String algorithm) {
            this.algorithm = algorithm;
        }

        public String getImplementation() {
            return algorithm;
        }

        public static Algorithm from(String value) {
            if (!StringUtils.isEmpty(value) && value.contains("512")) {
                return SHA_512;
            }
            return SHA_256;
        }
    }

    public enum Encoding {
        UTF_8, HEX;
    }


    private static volatile Digest instance;

    private Digest() {
    }

    public static Digest getInstance() {
        /*
        We use double checked locking and a non final instance, since we do not know beforehand whether we operate
        within a Sring context or not.  We also provide configuration support for the Spring singleton scope
        */
        if (instance == null) {
            synchronized (Digest.class) {
                if (instance == null) {
                    Digest.instance = new Digest();
                }
            }
        }
        return instance;
    }


    public byte[] getHash(Algorithm algorithm, String input) {
        if (StringUtils.isEmpty(input)) {
            return new byte[]{};
        }
        return getHash(algorithm, input.getBytes());
    }

    public byte[] getHash(Algorithm algorithm, byte[] input) {
        try {
            return MessageDigest.getInstance(algorithm.getImplementation()).digest(input);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public byte[] getSHA256Hash(byte[] base) {
        return getHash(Algorithm.SHA_256, base);
    }

    public byte[] getSHA512Hash(byte[] base) {
        return getHash(Algorithm.SHA_512, base);
    }

    public String getHashAsString(Algorithm algorithm, String input, Encoding encoding) {
        if (StringUtils.isEmpty(input)) {
            return "";
        }
        return getHashAsString(algorithm, input.getBytes(), encoding);

    }

    public String getHashAsString(Algorithm algorithm, byte[] input, Encoding encoding) {
        byte[] hash = getHash(algorithm, input);
        if (encoding == Encoding.UTF_8) {
            return new String(hash, Charset.forName("UTF-8"));
        } else {
            return Hex.encodeHexString(hash);
        }
    }

}

@@ -146,27 +146,95 @@
 ava.
-nio.charset.Charset
+io.InputStream;%0Aimport java.nio.charset.Charset;%0Aimport java.security.DigestInputStream
 ;%0Aim
@@ -379,16 +379,71 @@
 igest %7B%0A
+%0A    public static final int BUFFERSIZE_1M = 1048576;%0A%0A
     publ
@@ -551,16 +551,17 @@
 rithm;%0A%0A
+%0A
         
@@ -633,32 +633,33 @@
 thm;%0A        %7D%0A%0A
+%0A
         public S
@@ -723,24 +723,25 @@
 %0A        %7D%0A%0A
+%0A
         publ
@@ -1045,16 +1045,17 @@
 tance;%0A%0A
+%0A
     priv
@@ -1068,32 +1068,33 @@
 gest() %7B%0A    %7D%0A%0A
+%0A
     public stati
@@ -1805,32 +1805,33 @@
 ytes());%0A    %7D%0A%0A
+%0A
     public byte%5B
@@ -2097,32 +2097,582 @@
        %7D%0A    %7D%0A%0A
+%0A    public byte%5B%5D getHash(Algorithm algorithm, InputStream inputStream) %7B%0A        try %7B%0A            byte%5B%5D buffer = new byte%5BBUFFERSIZE_1M%5D;%0A            MessageDigest messageDigest = MessageDigest.getInstance(algorithm.getImplementation());%0A            try (DigestInputStream dis = new DigestInputStream(inputStream, messageDigest)) %7B%0A                while (dis.read(buffer) != -1);%0A            %7D%0A            return messageDigest.digest();%0A        %7D catch (Exception e) %7B%0A            throw new RuntimeException(e.getMessage(), e);%0A        %7D%0A    %7D%0A%0A%0A
     public byte%5B
@@ -2750,32 +2750,33 @@
 , base);%0A    %7D%0A%0A
+%0A
     public byte%5B
@@ -2854,32 +2854,33 @@
 , base);%0A    %7D%0A%0A
+%0A
     public Strin
@@ -3100,23 +3100,24 @@
 ding);%0A%0A
-
     %7D%0A%0A
+%0A
     publ

add hashing support for InputStreams