// Copyright (c) 2023, Sudipto Chandra
// All rights reserved. Check LICENSE file for details.

// ignore: library_annotations
@Tags(['vm-only'])

import 'dart:typed_data';

import 'package:hashlib/codecs.dart';
import 'package:hashlib/hashlib.dart';
import 'package:test/test.dart';

const seed = 0x9e3779b185ebca8d;
final cases = fromHex(
  '[encoded data, 4486 characters]',
);
final secret = cases.sublist(7, 7 + 136 + 11);

String sum([Iterable<int>? data]) {
  return xxh128.convert(data?.toList() ?? []).hex();
}

String seedsum([Iterable<int>? data]) {
  return XXH128().withSeed(seed).convert(data?.toList() ?? []).hex();
}

String secretSum([Iterable<int>? data]) {
  return XXH128(secret: secret).convert(data?.toList() ?? []).hex();
}

void main() {
  group('xxh3-128 test', () {
    test("xxh128sum", () {
      final input = String.fromCharCodes(cases.take(1));
      final output = "a6cd5e9392000f6ac44bdff4074eecdb";
      expect(xxh128sum(input), output);
    });
    test("with secret", () {
      expect(secretSum(cases.take(6)), '376bd91b6432f36d0b61c8aca7d4778f');
    });

    test('The secret length must be at least 136', () {
      for (int i = 0; i < 136; ++i) {
        var instance = xxh3_128.withSecret(Uint8List(i));
        expect(() => instance.convert([2]), throwsArgumentError);
      }
    });

    test("with input length = 0", () {
      expect(sum(), "99aa06d3014798d86001c324468d497f");
    });
    test("with input length = 0 and a seed", () {
      expect(seedsum(), "00feaa732a3ce25ea986dfc5d7605bfe");
    });
    test("with input length = 1", () {
      expect(sum(cases.take(1)), "a6cd5e9392000f6ac44bdff4074eecdb");
    });
    test("with input length = 1 and a seed", () {
      expect(seedsum(cases.take(1)), "20e49abcc53b3842032be332dd766ef8");
    });
    test("with input length = 6", () {
      expect(sum(cases.take(6)), "082afe0b8162d12a3e7039bdda43cfc6");
    });
    test("with input length = 6 and a seed", () {
      expect(seedsum(cases.take(6)), "014bd95a51ca5ddbc5b54d56038e4e40");
    });
    test("with input length = 12", () {
      expect(sum(cases.take(12)), "6e3efd8fc7802b18061a192713f69ad9");
    });
    test("with input length = 12 and a seed", () {
      expect(seedsum(cases.take(12)), "ff0d60acd02ed4015d92b5d7190b12d1");
    });
    test("with input length = 24", () {
      expect(sum(cases.take(24)), "0ce966e4678d37611e7044d28b1b901d");
    });
    test("with input length = 24 and a seed", () {
      expect(seedsum(cases.take(24)), "d7895ded1f62559dc6cbf92a70680b19");
    });
    test("with input length = 48", () {
      expect(sum(cases.take(48)), "a002ac4e5478227ef942219aed80f67b");
    });
    test("with input length = 48 and a seed", () {
      expect(seedsum(cases.take(48)), "bc689f4c0152fb443a94d91333ed395a");
    });
    test("with input length = 81", () {
      expect(sum(cases.take(81)), "4952f58181ab00425e8bafb9f95fb803");
    });
    test("with input length = 81 and a seed", () {
      expect(seedsum(cases.take(81)), "941e9469c46edd08dc50feb227515233");
    });
    test("with input length = 222", () {
      expect(sum(cases.take(222)), "337e09641b948717f1aebd597cec6b3a");
    });
    test("with input length = 222 and a seed", () {
      expect(seedsum(cases.take(222)), "4740af1ae0618b49c5871b3be4506a30");
    });
    test("with input length = 403", () {
      expect(sum(cases.take(403)), "1b6de21e332dd73dcdeb804d65c6dea4");
    });
    test("with input length = 403 and a seed", () {
      expect(seedsum(cases.take(403)), "bed311971e0be8f26259f6ecfd6443fd");
    });
    test("with input length = 512", () {
      expect(sum(cases.take(512)), "18d2d110dcc9bca1617e49599013cb6b");
    });
    test("with input length = 512 and a seed", () {
      expect(seedsum(cases.take(512)), "925d06b8ec5b80403ce457de14c27708");
    });
    test("with input length = 2048", () {
      expect(sum(cases.take(2048)), "f736557fd47073a5dd59e2c3a5f038e0");
    });
    test("with input length = 2048 and a seed", () {
      expect(seedsum(cases.take(2048)), "23cc3a2e75ebaaea66f81670669ababc");
    });
    test("with input length = 2240", () {
      expect(sum(cases.take(2240)), "ccb134fbfa7ce49d6e73a90539cf2948");
    });
    test("with input length = 2240 and a seed", () {
      expect(seedsum(cases.take(2240)), "e40842f585875ba9757ba8487d1b5247");
    });
    test("with input length = 2237", () {
      expect(sum(cases.take(2237)), "0cdabf3f3c98b371f403cea1763cd9cc");
    });
    test("with input length = 2237 and a seed", () {
      expect(seedsum(cases.take(2237)), "3eef572c60cbcdc0f7a5385336bef410");
    });
  });
}
