import 'dart:math';

import '../../application/ports.dart';

const _crockfordBase32 = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';

final class LocalIdGenerator implements IdGenerator {
  LocalIdGenerator({Random? random}) : _random = random ?? Random.secure();

  final Random _random;

  @override
  String newId() => newUlid();

  String newUlid({DateTime? now}) {
    final timestamp = (now ?? DateTime.now().toUtc()).millisecondsSinceEpoch;
    final buffer = StringBuffer();

    var remainingTimestamp = timestamp;
    final timestampChars = List<String>.filled(10, '0');
    for (var index = 9; index >= 0; index--) {
      timestampChars[index] = _crockfordBase32[remainingTimestamp & 0x1F];
      remainingTimestamp >>= 5;
    }
    buffer.writeAll(timestampChars);

    for (var index = 0; index < 16; index++) {
      buffer.write(_crockfordBase32[_random.nextInt(32)]);
    }

    return buffer.toString();
  }
}
