// 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.

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<List<int>>([], (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<List<int>>(<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<List<int>>([], (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<List<int>>([],
      (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<List<int>>([], (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].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<List<int>>([], (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<List<int>>([], (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<List<int>>([], (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();
}
