package ch.threema.domain.fs;

import java.util.Arrays;

import androidx.annotation.NonNull;
import ch.threema.base.ThreemaException;
import ch.threema.domain.protocol.csp.ProtocolDefines;

import static ch.threema.common.ByteArrayExtensionsKt.toHexString;
import static ch.threema.common.SecureRandomExtensionsKt.generateRandomBytes;
import static ch.threema.common.SecureRandomExtensionsKt.secureRandom;

/**
 * Value Class for a DH session ID (consisting of {@link ProtocolDefines.FS_SESSION_ID_LENGTH} bytes).
 */
public class DHSessionId implements Comparable<DHSessionId> {
    private final @NonNull byte[] value;

    /**
     * Generate a new random session ID.
     */
    public DHSessionId() {
        this.value = generateRandomBytes(secureRandom(), ProtocolDefines.FS_SESSION_ID_LENGTH);
    }

    public DHSessionId(@NonNull byte[] value) throws DHSessionId.InvalidDHSessionIdException {
        if (value.length != ProtocolDefines.FS_SESSION_ID_LENGTH) {
            throw new DHSessionId.InvalidDHSessionIdException("Invalid session ID length " + value.length);
        }
        this.value = value;
    }

    @NonNull
    public byte[] get() {
        return this.value;
    }

    /**
     * Returns a hexadecimal string representation of the token.
     */
    @Override
    public @NonNull String toString() {
        return toHexString(this.value);
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) return true;
        if (o == null || this.getClass() != o.getClass()) return false;
        final DHSessionId that = (DHSessionId) o;
        return Arrays.equals(this.value, that.value);
    }

    @Override
    public int hashCode() {
        return Arrays.hashCode(this.value);
    }

    @Override
    public int compareTo(@NonNull DHSessionId o) {
        for (int i = 0; i < ProtocolDefines.FS_SESSION_ID_LENGTH; i++) {
            if (this.value[i] != o.value[i]) {
                return ((int) this.value[i] & 0xff) - ((int) o.value[i] & 0xff);
            }
        }
        return 0;
    }

    public static class InvalidDHSessionIdException extends ThreemaException {
        public InvalidDHSessionIdException(final String msg) {
            super(msg);
        }
    }
}
