// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:async';

import 'package:convert/convert.dart';
import 'package:test/test.dart';

void main() {
  group("encoder", () {
    test("converts byte arrays to hex", () {
      expect(hex.encode([0x1a, 0xb2, 0x3c, 0xd4]), equals("1ab23cd4"));
      expect(hex.encode([0x00, 0x01, 0xfe, 0xff]), equals("0001feff"));
    });

    group("with chunked conversion", () {
      test("converts byte arrays to hex", () {
        var results = <String>[];
        var controller = new StreamController<String>(sync: true);
        controller.stream.listen(results.add);
        var sink = hex.encoder.startChunkedConversion(controller.sink);

        sink.add([0x1a, 0xb2, 0x3c, 0xd4]);
        expect(results, equals(["1ab23cd4"]));

        sink.add([0x00, 0x01, 0xfe, 0xff]);
        expect(results, equals(["1ab23cd4", "0001feff"]));
      });

      test("handles empty and single-byte lists", () {
        var results = <String>[];
        var controller = new StreamController<String>(sync: true);
        controller.stream.listen(results.add);
        var sink = hex.encoder.startChunkedConversion(controller.sink);

        sink.add([]);
        expect(results, equals([""]));

        sink.add([0x00]);
        expect(results, equals(["", "00"]));

        sink.add([]);
        expect(results, equals(["", "00", ""]));
      });
    });

    test("rejects non-bytes", () {
      expect(() => hex.encode([0x100]), throwsFormatException);

      var sink = hex.encoder.startChunkedConversion(
          new StreamController(sync: true));
      expect(() => sink.add([0x100]), throwsFormatException);
    });
  });

  group("decoder", () {
    test("converts hex to byte arrays", () {
      expect(hex.decode("1ab23cd4"), equals([0x1a, 0xb2, 0x3c, 0xd4]));
      expect(hex.decode("0001feff"), equals([0x00, 0x01, 0xfe, 0xff]));
    });

    test("supports uppercase letters", () {
      expect(hex.decode("0123456789ABCDEFabcdef"), equals([
        0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef
      ]));
    });

    group("with chunked conversion", () {
      List<List<int>> results;
      var sink;
      setUp(() {
        results = [];
        var controller = new StreamController<List<int>>(sync: true);
        controller.stream.listen(results.add);
        sink = hex.decoder.startChunkedConversion(controller.sink);
      });

      test("converts hex to byte arrays", () {
        sink.add("1ab23cd4");
        expect(results, equals([[0x1a, 0xb2, 0x3c, 0xd4]]));

        sink.add("0001feff");
        expect(results,
            equals([[0x1a, 0xb2, 0x3c, 0xd4], [0x00, 0x01, 0xfe, 0xff]]));
      });

      test("supports trailing digits split across chunks", () {
        sink.add("1ab23");
        expect(results, equals([[0x1a, 0xb2]]));

        sink.add("cd");
        expect(results, equals([[0x1a, 0xb2], [0x3c]]));

        sink.add("40001");
        expect(results, equals([[0x1a, 0xb2], [0x3c], [0xd4, 0x00, 0x01]]));

        sink.add("feff");
        expect(results,
            equals([[0x1a, 0xb2], [0x3c], [0xd4, 0x00, 0x01], [0xfe, 0xff]]));
      });

      test("supports empty strings", () {
        sink.add("");
        expect(results, isEmpty);

        sink.add("0");
        expect(results, equals([[]]));

        sink.add("");
        expect(results, equals([[]]));

        sink.add("0");
        expect(results, equals([[], [0x00]]));

        sink.add("");
        expect(results, equals([[], [0x00]]));
      });

      test("rejects odd length detected in close()", () {
        sink.add("1ab23");
        expect(results, equals([[0x1a, 0xb2]]));
        expect(() => sink.close(), throwsFormatException);
      });

      test("rejects odd length detected in addSlice()", () {
        sink.addSlice("1ab23cd", 0, 5, false);
        expect(results, equals([[0x1a, 0xb2]]));

        expect(() => sink.addSlice("1ab23cd", 5, 7, true),
            throwsFormatException);
      });
    });

    group("rejects non-hex character", () {
      for (var char in
             ["g", "G", "/", ":", "@", "`", "\x00", "\u0141", "\u{10041}"]) {
        test('"$char"', () {
          expect(() => hex.decode("a$char"), throwsFormatException);
          expect(() => hex.decode("${char}a"), throwsFormatException);

          var sink = hex.decoder.startChunkedConversion(
              new StreamController(sync: true));
          expect(() => sink.add(char), throwsFormatException);
        });
      }
    });

    test("rejects odd length detected in convert()", () {
      expect(() => hex.decode("1ab23cd"), throwsFormatException);
    });
  });
}
