//
// Copyright 2023 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
use std::ops::Range;
use std::sync::LazyLock;

use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint};

pub(crate) static BASE_POINTS: LazyLock<[RistrettoPoint; 3]> = LazyLock::new(|| {
    COMPRESSED_BASE_POINTS_RAW.map(|bytes| {
        let compressed = CompressedRistretto::from_slice(&bytes)
            .expect("can create compressed ristretto from bytes");
        compressed.decompress().expect("can decompress ristretto")
    })
});

const COMPRESSED_BASE_POINTS_RAW: [[u8; 32]; 3] = [
    [
        0x60, 0xb9, 0x93, 0x66, 0x3a, 0x3d, 0xae, 0xcc, 0x4c, 0x85, 0x2f, 0x53, 0x35, 0x47, 0xe3,
        0x5, 0x38, 0x8c, 0x2a, 0x50, 0xa5, 0x83, 0x93, 0xea, 0x27, 0x7d, 0xe4, 0xab, 0xf3, 0xde,
        0x54, 0x3a,
    ],
    [
        0xf2, 0xb6, 0xf1, 0xc8, 0x26, 0xfa, 0x36, 0x40, 0x20, 0x6f, 0x3b, 0x58, 0xb2, 0x28, 0x6b,
        0xde, 0xfd, 0xfd, 0xa6, 0xa5, 0x4f, 0xf9, 0x2, 0xf2, 0x4, 0xa7, 0x2d, 0xe7, 0x37, 0xd2,
        0x61, 0x57,
    ],
    [
        0x6, 0x6, 0xbd, 0x3a, 0xbf, 0xce, 0x4e, 0x96, 0x17, 0xd4, 0x48, 0xfb, 0x2c, 0xae, 0xb6,
        0xcc, 0x2, 0x8e, 0xc9, 0xa2, 0xb6, 0x2b, 0x10, 0xb3, 0xd9, 0xeb, 0x29, 0x48, 0xda, 0x6f,
        0x3f, 0x53,
    ],
];

// Going past 37^48 will overflow the Scalar. See nickname_scalar implementation for details.
pub(crate) const MAX_NICKNAME_LENGTH: usize = 48;
pub(crate) const DISCRIMINATOR_RANGES: [Range<usize>; 8] = [
    1..100,
    100..1_000,
    1_000..10_000,
    10_000..100_000,
    100_000..1_000_000,
    1_000_000..10_000_000,
    10_000_000..100_000_000,
    100_000_000..1_000_000_000,
];

pub(crate) const CANDIDATES_PER_RANGE: [usize; 8] = [4, 3, 3, 2, 2, 2, 2, 2];

pub const USERNAME_LINK_ENTROPY_SIZE: usize = 32;

pub(crate) const USERNAME_LINK_LABEL_ENCRYPTION_KEY: &[u8] = b"Signal Username Link Encryption Key";
pub(crate) const USERNAME_LINK_LABEL_AUTHENTICATION_KEY: &[u8] =
    b"Signal Username Link Authentication Key";
pub(crate) const USERNAME_LINK_HMAC_LEN: usize = 32;
pub(crate) const USERNAME_LINK_KEY_SIZE: usize = 32;
pub(crate) const USERNAME_LINK_IV_SIZE: usize = 16;

#[cfg(test)]
mod test {
    use zkgroup::common::sho::Sho;

    use super::*;

    #[test]
    fn generate_points() {
        let mut sho = Sho::new(b"Signal_Username_20230130_Constant_Points_Generate", b"");
        for p in BASE_POINTS.iter() {
            assert_eq!(&sho.get_point(), p);
        }
    }
}
