// Copyright (c) 2013, 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.

// @dart = 2.9

import 'dart:async';
import 'dart:io';
import 'dart:typed_data';

import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";

void testZLibDeflateEmpty() {
  asyncStart();
  var controller = new StreamController(sync: true);
  controller.stream.transform(new ZLibEncoder(gzip: false, level: 6)).fold([],
      (buffer, data) {
    buffer.addAll(data);
    return buffer;
  }).then((data) {
    Expect.listEquals([120, 156, 3, 0, 0, 0, 0, 1], data);
    asyncEnd();
  });
  controller.close();
}

void testZLibDeflateEmptyGzip() {
  asyncStart();
  var controller = new StreamController(sync: true);
  controller.stream
      .transform(new ZLibEncoder(gzip: true, level: 6))
      .fold(<int>[], (buffer, data) {
    buffer.addAll(data);
    return buffer;
  }).then((data) {
    Expect.isTrue(data.length > 0);
    Expect.listEquals([], new ZLibDecoder().convert(data));
    asyncEnd();
  });
  controller.close();
}

void testZLibDeflate(List<int> data) {
  asyncStart();
  var controller = new StreamController(sync: true);
  controller.stream.transform(new ZLibEncoder(gzip: false, level: 6)).fold([],
      (buffer, data) {
    buffer.addAll(data);
    return buffer;
  }).then((data) {
    Expect.listEquals([
      120,
      156,
      99,
      96,
      100,
      98,
      102,
      97,
      101,
      99,
      231,
      224,
      4,
      0,
      0,
      175,
      0,
      46
    ], data);
    asyncEnd();
  });
  controller.add(data);
  controller.close();
}

void testZLibDeflateGZip(List<int> data) {
  asyncStart();
  var controller = new StreamController(sync: true);
  controller.stream.transform(new ZLibEncoder(gzip: true)).fold([],
      (buffer, data) {
    buffer.addAll(data);
    return buffer;
  }).then((data) {
    Expect.equals(30, data.length);
    Expect.listEquals(
        [
          99,
          96,
          100,
          98,
          102,
          97,
          101,
          99,
          231,
          224,
          4,
          0,
          70,
          215,
          108,
          69,
          10,
          0,
          0,
          0
        ],
        // Skip header, as it can change.
        data.sublist(10));
    asyncEnd();
  });
  controller.add(data);
  controller.close();
}

void testZLibDeflateRaw(List<int> data) {
  asyncStart();
  var controller = new StreamController(sync: true);
  controller.stream.transform(new ZLibEncoder(raw: true, level: 6)).fold([],
      (buffer, data) {
    buffer.addAll(data);
    return buffer;
  }).then((data) {
    Expect
        .listEquals([99, 96, 100, 98, 102, 97, 101, 99, 231, 224, 4, 0], data);
    asyncEnd();
  });
  controller.add(data);
  controller.close();
}

void testZLibDeflateInvalidLevel() {
  test2(gzip, level) {
    [true, false].forEach((gzip) {
      [-2, -20, 10, 42, null, "9"].forEach((level) {
        Expect.throwsArgumentError(
            () => new ZLibEncoder(gzip: gzip, level: level),
            "'level' must be in range -1..9");
      });
    });
  }

  ;
}

void testZLibInflate(List<int> data) {
  [true, false].forEach((gzip) {
    [
      ZLibOption.strategyFiltered,
      ZLibOption.strategyHuffmanOnly,
      ZLibOption.strategyRle,
      ZLibOption.strategyFixed,
      ZLibOption.strategyDefault,
    ].forEach((strategy) {
      [3, 6, 9].forEach((level) {
        asyncStart();
        var controller = new StreamController(sync: true);
        controller.stream
            .transform(
                new ZLibEncoder(gzip: gzip, level: level, strategy: strategy))
            .transform(new ZLibDecoder())
            .fold([], (buffer, data) {
          buffer.addAll(data);
          return buffer;
        }).then((inflated) {
          Expect.listEquals(data, inflated);
          asyncEnd();
        });
        controller.add(data);
        controller.close();
      });
    });
  });
}

void testZLibInflateRaw(List<int> data) {
  [3, 6, 9].forEach((level) {
    asyncStart();
    var controller = new StreamController(sync: true);
    controller.stream
        .transform(new ZLibEncoder(raw: true, level: level))
        .transform(new ZLibDecoder(raw: true))
        .fold([], (buffer, data) {
      buffer.addAll(data);
      return buffer;
    }).then((inflated) {
      Expect.listEquals(data, inflated);
      asyncEnd();
    });
    controller.add(data);
    controller.close();
  });
}

void testZLibInflateSync(List<int> data) {
  [true, false].forEach((gzip) {
    [3, 6, 9].forEach((level) {
      var encoded = new ZLibEncoder(gzip: gzip, level: level).convert(data);
      var decoded = new ZLibDecoder().convert(encoded);
      Expect.listEquals(data, decoded);
    });
  });
}

void testZlibInflateThrowsWithSmallerWindow() {
  var data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
  var encoder = new ZLibEncoder(windowBits: 10);
  var encodedData = encoder.convert(data);
  var decoder = new ZLibDecoder(windowBits: 8);
  Expect.throws(() => decoder.convert(encodedData));
}

void testZlibInflateWithLargerWindow() {
  var data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

  [true, false].forEach((gzip) {
    [3, 6, 9].forEach((level) {
      asyncStart();
      var controller = new StreamController(sync: true);
      controller.stream
          .transform(new ZLibEncoder(gzip: gzip, level: level, windowBits: 8))
          .transform(new ZLibDecoder(windowBits: 10))
          .fold([], (buffer, data) {
        buffer.addAll(data);
        return buffer;
      }).then((inflated) {
        Expect.listEquals(data, inflated);
        asyncEnd();
      });
      controller.add(data);
      controller.close();
    });
  });
}

void testZlibWithDictionary() {
  var dict = [102, 111, 111, 98, 97, 114];
  var data = [98, 97, 114, 102, 111, 111];

  [3, 6, 9].forEach((level) {
    var encoded = new ZLibEncoder(level: level, dictionary: dict).convert(data);
    var decoded = new ZLibDecoder(dictionary: dict).convert(encoded);
    Expect.listEquals(data, decoded);
  });
}

var generateListTypes = [
  (list) => list,
  (list) => new Uint8List.fromList(list),
  (list) => new Int8List.fromList(list),
  (list) => new Uint16List.fromList(list),
  (list) => new Int16List.fromList(list),
  (list) => new Uint32List.fromList(list),
  (list) => new Int32List.fromList(list),
];

var generateViewTypes = [
  (list) => new Uint8List.view((new Uint8List.fromList(list)).buffer, 1, 8),
  (list) => new Int8List.view((new Int8List.fromList(list)).buffer, 1, 8),
  (list) => new Uint16List.view((new Uint16List.fromList(list)).buffer, 2, 6),
  (list) => new Int16List.view((new Int16List.fromList(list)).buffer, 2, 6),
  (list) => new Uint32List.view((new Uint32List.fromList(list)).buffer, 4, 4),
  (list) => new Int32List.view((new Int32List.fromList(list)).buffer, 4, 4),
];

void main() {
  asyncStart();
  testZLibDeflateEmpty();
  testZLibDeflateEmptyGzip();
  testZLibDeflateInvalidLevel();
  generateListTypes.forEach((f) {
    var data = f([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
    testZLibDeflate(data);
    testZLibDeflateGZip(data);
    testZLibDeflateRaw(data);
    testZLibInflate(data);
    testZLibInflateSync(data);
    testZLibInflateRaw(data);
  });
  generateViewTypes.forEach((f) {
    var data = f([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
    testZLibInflate(data);
    testZLibInflateSync(data);
    testZLibInflateRaw(data);
  });
  testZlibInflateThrowsWithSmallerWindow();
  testZlibInflateWithLargerWindow();
  testZlibWithDictionary();
  asyncEnd();
}
