package com.avg.zaap.crashlibrary.core.hash;

import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import com.avg.zaap.crashlibrary.core.logger.CrashLogger;

import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * This class serves as the default hash generator. Generates a SHA-1 hash.
 * <p>
 * Created by marek.osvald on 11.5.2016.
 */
public class HashGenerator implements IHashGenerator {

    private static final String TAG = HashGenerator.class.getSimpleName();

    @SuppressWarnings("SpellCheckingInspection")
    private static final char[] HEX_CHARS = "0123456789abcdef".toCharArray();
    private static final int INT_SIZE = 4;
    private static final String SHA_1 = "SHA-1";

    @Override
    @Nullable
    public String generateHash(@NonNull StackTraceElement[] stacktrace) {
        ByteBuffer byteBuffer = ByteBuffer.allocate(stacktrace.length * INT_SIZE);

        for (StackTraceElement element : stacktrace) {
            byteBuffer.putInt(element.hashCode());
        }

        byte[] bytes = byteBuffer.array();

        try {
            final MessageDigest sha1 = MessageDigest.getInstance(SHA_1);
            final byte[] digest = sha1.digest(bytes);
            return bytesToHex(digest);
        } catch (NoSuchAlgorithmException e) {
            CrashLogger.e(TAG, "Unable to retrieve an instance of SHA-1, original exception %s: %s", e.getClass().getSimpleName(), e.getMessage());
        }

        return null;
    }

    private String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) {
            int value = bytes[j] & 0xFF; // convert to byte value, but also allows s
            hexChars[j * 2] = HEX_CHARS[value >>> 4]; // bit-shift without sign, top byte
            hexChars[j * 2 + 1] = HEX_CHARS[value & 0x0F]; // bottom byte
        }

        return new String(hexChars);
    }

}
