// 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 xxh3.convert(data?.toList() ?? []).hex();
}

String seedSum(int seed, [Iterable<int>? data]) {
  return XXH3(seed: seed).convert(data?.toList() ?? []).hex();
}

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

void main() {
  group('XXH3 test', () {
    test("xxh3code", () {
      var input = String.fromCharCodes(cases.take(12));
      final expected = 0xa713daf0dfbb77e7;
      expect(xxh3code(input), expected);
    });

    test("xxh3sum", () {
      var input = String.fromCharCodes(cases.take(12));
      final expected = 'a713daf0dfbb77e7';
      expect(xxh3sum(input), expected);
    });

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

    test("withSeed overrides the seed", () {
      var instance = XXH3(seed: 0).withSeed(seed);
      expect(instance.convert([]).hex(), "a8a6b918b2f0364a");
    });

    test("with input length = 0", () {
      expect(sum(), "2d06800538d394c2");
    });
    test("with input length = 0 and a seed", () {
      expect(seedSum(seed), "a8a6b918b2f0364a");
    });
    test("with input length = 1", () {
      expect(sum(cases.take(1)), "c44bdff4074eecdb");
    });
    test("with input length = 1 and a seed", () {
      expect(seedSum(seed, cases.take(1)), "032be332dd766ef8");
    });
    test("with input length = 6", () {
      expect(sum(cases.take(6)), "27b56a84cd2d7325");
    });
    test("with input length = 6 and a seed", () {
      expect(seedSum(seed, cases.take(6)), "84589c116ab59ab9");
    });
    test("with input length = 12", () {
      expect(sum(cases.take(12)), "a713daf0dfbb77e7");
    });
    test("with input length = 12 and a seed", () {
      expect(seedSum(seed, cases.take(12)), "e7303e1b2336de0e");
    });
    test("with input length = 24", () {
      expect(sum(cases.take(24)), "a3fe70bf9d3510eb");
    });
    test("with input length = 24 and a seed", () {
      expect(seedSum(seed, cases.take(24)), "850e80fc35bdd690");
    });
    test("with input length = 48", () {
      expect(sum(cases.take(48)), "397da259ecba1f11");
    });
    test("with input length = 48 and a seed", () {
      expect(seedSum(seed, cases.take(48)), "adc2cbaa44acc616");
    });
    test("with input length = 80", () {
      expect(sum(cases.take(80)), "bcdefbbb2c47c90a");
    });
    test("with input length = 80 and a seed", () {
      expect(seedSum(seed, cases.take(80)), "c6dd0cb699532e73");
    });
    test("with input length = 195", () {
      expect(sum(cases.take(195)), "cd94217ee362ec3a");
    });
    test("with input length = 195 and a seed", () {
      expect(seedSum(seed, cases.take(195)), "ba68003d370cb3d9");
    });
    test("with input length = 403", () {
      expect(sum(cases.take(403)), "cdeb804d65c6dea4");
    });
    test("with input length = 403 and a seed", () {
      expect(seedSum(seed, cases.take(403)), "6259f6ecfd6443fd");
    });
    test("with input length = 512", () {
      expect(sum(cases.take(512)), "617e49599013cb6b");
    });
    test("with input length = 512 and a seed", () {
      expect(seedSum(seed, cases.take(512)), "3ce457de14c27708");
    });
    test("with input length = 2048", () {
      expect(sum(cases.take(2048)), "dd59e2c3a5f038e0");
    });
    test("with input length = 2048 and a seed", () {
      expect(seedSum(seed, cases.take(2048)), "66f81670669ababc");
    });
    test("with input length = 2240", () {
      expect(sum(cases.take(2240)), "6e73a90539cf2948");
    });
    test("with input length = 2240 and a seed", () {
      expect(seedSum(seed, cases.take(2240)), "757ba8487d1b5247");
    });
    test("with input length = 2243", () {
      expect(sum(cases.take(2243)), "fdd97ddf7a83e7a9");
    });
    test("with input length = 2243 and a seed", () {
      expect(seedSum(seed, cases.take(2243)), "a2115d49b6729aed");
    });

    // test("with secret, length = 0", () {
    //   expect(secretSum(), "6775fd10343c92c3");
    // });
    // test("with secret, length = 1", () {
    //   expect(secretSum(cases.take(1)), "c3382c326e24e3cd");
    // });
    test("with secret, length = 6", () {
      expect(secretSum(cases.take(6)), "82c90ab0519369ad");
    });
    test("with secret, length = 12", () {
      expect(secretSum(cases.take(12)), "14631e773b78ec57");
    });
    test("with secret, length = 24", () {
      expect(secretSum(cases.take(24)), "cdd5542e4a9d9fe8");
    });
    test("with secret, length = 48", () {
      expect(secretSum(cases.take(48)), "33abd54d094b2534");
    });
    test("with secret, length = 80", () {
      expect(secretSum(cases.take(80)), "e687ba1684965297");
    });
    test("with secret, length = 195", () {
      expect(secretSum(cases.take(195)), "a057273f5eecfb20");
    });
    // test("with secret, length = 403", () {
    //   expect(secretSum(cases.take(403)), "f9c0ba5ba3af70b8");
    // });
    // test("with secret, length = 512", () {
    //   expect(secretSum(cases.take(512)), "7896e65dcfa09071");
    // });
    // test("with secret, length = 2048", () {
    //   expect(secretSum(cases.take(2048)), "d6545db87ecfd98c");
    // });
    // test("with secret, length = 2243", () {
    //   expect(secretSum(cases.take(2243)), "887810081c32460a");
    // });
  });
}
