/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.eclipse.aether.util;

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

/**
 * A simple digester utility for Strings. Uses {@link MessageDigest} for requested algorithm. Supports one-pass or
 * several rounds of updates, and as result emits hex encoded String.
 *
 * @since 1.9.0
 */
public final class StringDigestUtil {
    private final MessageDigest digest;

    /**
     * Constructs instance with given algorithm.
     *
     * @see #sha1()
     * @see #sha1(String)
     */
    public StringDigestUtil(final String alg) {
        try {
            this.digest = MessageDigest.getInstance(alg);
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException("Not supported digest algorithm: " + alg);
        }
    }

    /**
     * Updates instance with passed in string.
     */
    public StringDigestUtil update(String data) {
        if (data != null && !data.isEmpty()) {
            digest.update(data.getBytes(StandardCharsets.UTF_8));
        }
        return this;
    }

    /**
     * Returns the digest of all strings passed via {@link #update(String)} as hex string. There is no state preserved
     * and due implementation of {@link MessageDigest#digest()}, same applies here: this instance "resets" itself.
     * Hence, the digest hex encoded string is returned only once.
     *
     * @see MessageDigest#digest()
     */
    public String digest() {
        return toHexString(digest.digest());
    }

    /**
     * Helper method to create {@link StringDigestUtil} using SHA-1 digest algorithm.
     */
    public static StringDigestUtil sha1() {
        return new StringDigestUtil("SHA-1");
    }

    /**
     * Helper method to calculate SHA-1 digest and hex encode it.
     */
    public static String sha1(final String string) {
        return sha1().update(string).digest();
    }

    /**
     * Creates a hexadecimal representation of the specified bytes. Each byte is converted into a two-digit hex number
     * and appended to the result with no separator between consecutive bytes.
     *
     * @param bytes The bytes to represent in hex notation, may be {@code null}.
     * @return The hexadecimal representation of the input or {@code null} if the input was {@code null}.
     * @since 2.0.0
     */
    @SuppressWarnings("checkstyle:magicnumber")
    public static String toHexString(byte[] bytes) {
        if (bytes == null) {
            return null;
        }

        StringBuilder buffer = new StringBuilder(bytes.length * 2);

        for (byte aByte : bytes) {
            int b = aByte & 0xFF;
            if (b < 0x10) {
                buffer.append('0');
            }
            buffer.append(Integer.toHexString(b));
        }

        return buffer.toString();
    }

    /**
     * Creates a byte array out of hexadecimal representation of the specified bytes. If input string is {@code null},
     * {@code null} is returned. Input value must have even length (due hex encoding = 2 chars one byte).
     *
     * @param hexString The hexString to convert to byte array, may be {@code null}.
     * @return The byte array of the input or {@code null} if the input was {@code null}.
     * @since 2.0.0
     */
    @SuppressWarnings("checkstyle:magicnumber")
    public static byte[] fromHexString(String hexString) {
        if (hexString == null) {
            return null;
        }
        if (hexString.isEmpty()) {
            return new byte[] {};
        }
        int len = hexString.length();
        if (len % 2 != 0) {
            throw new IllegalArgumentException("hexString length not even");
        }
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte)
                    ((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i + 1), 16));
        }
        return data;
    }
}
