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

part of dart.io;

/**
 * Exposes ZLib options for input parameters.
 *
 * See http://www.zlib.net/manual.html for more documentation.
 */
abstract class ZLibOption {
  /// Minimal value for [ZLibCodec.windowBits], [ZLibEncoder.windowBits]
  /// and [ZLibDecoder.windowBits].
  static const int minWindowBits = 8;
  @Deprecated("Use minWindowBits instead")
  static const int MIN_WINDOW_BITS = 8;

  /// Maximal value for [ZLibCodec.windowBits], [ZLibEncoder.windowBits]
  /// and [ZLibDecoder.windowBits].
  static const int maxWindowBits = 15;
  @Deprecated("Use maxWindowBits instead")
  static const int MAX_WINDOW_BITS = 15;

  /// Default value for [ZLibCodec.windowBits], [ZLibEncoder.windowBits]
  /// and [ZLibDecoder.windowBits].
  static const int defaultWindowBits = 15;
  @Deprecated("Use defaultWindowBits instead")
  static const int DEFAULT_WINDOW_BITS = 15;

  /// Minimal value for [ZLibCodec.level] and [ZLibEncoder.level].
  static const int minLevel = -1;
  @Deprecated("Use minLevel instead")
  static const int MIN_LEVEL = -1;

  /// Maximal value for [ZLibCodec.level] and [ZLibEncoder.level]
  static const int maxLevel = 9;
  @Deprecated("Use maxLevel instead")
  static const int MAX_LEVEL = 9;

  /// Default value for [ZLibCodec.level] and [ZLibEncoder.level].
  static const int defaultLevel = 6;
  @Deprecated("Use defaultLevel instead")
  static const int DEFAULT_LEVEL = 6;

  /// Minimal value for [ZLibCodec.memLevel] and [ZLibEncoder.memLevel].
  static const int minMemLevel = 1;
  @Deprecated("Use minMemLevel instead")
  static const int MIN_MEM_LEVEL = 1;

  /// Maximal value for [ZLibCodec.memLevel] and [ZLibEncoder.memLevel].
  static const int maxMemLevel = 9;
  @Deprecated("Use maxMemLevel instead")
  static const int MAX_MEM_LEVEL = 9;

  /// Default value for [ZLibCodec.memLevel] and [ZLibEncoder.memLevel].
  static const int defaultMemLevel = 8;
  @Deprecated("Use defaultMemLevel instead")
  static const int DEFAULT_MEM_LEVEL = 8;

  /// Recommended strategy for data produced by a filter (or predictor)
  static const int strategyFiltered = 1;
  @Deprecated("Use strategyFiltered instead")
  static const int STRATEGY_FILTERED = 1;

  /// Use this strategy to force Huffman encoding only (no string match)
  static const int strategyHuffmanOnly = 2;
  @Deprecated("Use strategyHuffmanOnly instead")
  static const int STRATEGY_HUFFMAN_ONLY = 2;

  /// Use this strategy to limit match distances to one (run-length encoding)
  static const int strategyRle = 3;
  @Deprecated("Use strategyRle instead")
  static const int STRATEGY_RLE = 3;

  /// This strategy prevents the use of dynamic Huffman codes, allowing for a
  /// simpler decoder
  static const int strategyFixed = 4;
  @Deprecated("Use strategyFixed instead")
  static const int STRATEGY_FIXED = 4;

  /// Recommended strategy for normal data
  static const int strategyDefault = 0;
  @Deprecated("Use strategyDefault instead")
  static const int STRATEGY_DEFAULT = 0;
}

/**
 * An instance of the default implementation of the [ZLibCodec].
 */
const ZLibCodec zlib = const ZLibCodec._default();
@Deprecated("Use zlib instead")
const ZLibCodec ZLIB = zlib;

/**
 * The [ZLibCodec] encodes raw bytes to ZLib compressed bytes and decodes ZLib
 * compressed bytes to raw bytes.
 */
class ZLibCodec extends Codec<List<int>, List<int>> {
  /**
   * When true, `GZip` frames will be added to the compressed data.
   */
  final bool gzip;

  /**
   * The compression-[level] can be set in the range of `-1..9`, with `6` being
   * the default compression level. Levels above `6` will have higher
   * compression rates at the cost of more CPU and memory usage. Levels below
   * `6` will use less CPU and memory at the cost of lower compression rates.
   */
  final int level;

  /**
   * Specifies how much memory should be allocated for the internal compression
   * state. `1` uses minimum memory but is slow and reduces compression ratio;
   * `9` uses maximum memory for optimal speed. The default value is `8`.
   *
   * The memory requirements for deflate are (in bytes):
   *
   *     (1 << (windowBits + 2)) +  (1 << (memLevel + 9))
   * that is: 128K for windowBits = 15 + 128K for memLevel = 8 (default values)
   */
  final int memLevel;

  /**
   * Tunes the compression algorithm. Use the value strategyDefault for normal
   * data, strategyFiltered for data produced by a filter (or predictor),
   * strategyHuffmanOnly to force Huffman encoding only (no string match), or
   * strategyRle to limit match distances to one (run-length encoding).
   */
  final int strategy;

  /**
   * Base two logarithm of the window size (the size of the history buffer). It
   * should be in the range 8..15. Larger values result in better compression at
   * the expense of memory usage. The default value is 15
   */
  final int windowBits;

  /**
   * When true, deflate generates raw data with no zlib header or trailer, and
   * will not compute an adler32 check value
   */
  final bool raw;

  /**
   * Initial compression dictionary.
   *
   * It should consist of strings (byte sequences) that are likely to be
   * encountered later in the data to be compressed, with the most commonly used
   * strings preferably put towards the end of the dictionary. Using a
   * dictionary is most useful when the data to be compressed is short and can
   * be predicted with good accuracy; the data can then be compressed better
   * than with the default empty dictionary.
   */
  final List<int>? dictionary;

  ZLibCodec(
      {this.level: ZLibOption.defaultLevel,
      this.windowBits: ZLibOption.defaultWindowBits,
      this.memLevel: ZLibOption.defaultMemLevel,
      this.strategy: ZLibOption.strategyDefault,
      this.dictionary,
      this.raw: false,
      this.gzip: false}) {
    _validateZLibeLevel(level);
    _validateZLibMemLevel(memLevel);
    _validateZLibStrategy(strategy);
    _validateZLibWindowBits(windowBits);
  }

  const ZLibCodec._default()
      : level = ZLibOption.defaultLevel,
        windowBits = ZLibOption.defaultWindowBits,
        memLevel = ZLibOption.defaultMemLevel,
        strategy = ZLibOption.strategyDefault,
        raw = false,
        gzip = false,
        dictionary = null;

  /**
   * Get a [ZLibEncoder] for encoding to `ZLib` compressed data.
   */
  ZLibEncoder get encoder => new ZLibEncoder(
      gzip: false,
      level: level,
      windowBits: windowBits,
      memLevel: memLevel,
      strategy: strategy,
      dictionary: dictionary,
      raw: raw);

  /**
   * Get a [ZLibDecoder] for decoding `ZLib` compressed data.
   */
  ZLibDecoder get decoder =>
      new ZLibDecoder(windowBits: windowBits, dictionary: dictionary, raw: raw);
}

/**
 * An instance of the default implementation of the [GZipCodec].
 */
const GZipCodec gzip = const GZipCodec._default();
@Deprecated("Use gzip instead")
const GZipCodec GZIP = gzip;

/**
 * The [GZipCodec] encodes raw bytes to GZip compressed bytes and decodes GZip
 * compressed bytes to raw bytes.
 *
 * The difference between [ZLibCodec] and [GZipCodec] is that the [GZipCodec]
 * wraps the `ZLib` compressed bytes in `GZip` frames.
 */
class GZipCodec extends Codec<List<int>, List<int>> {
  /**
   * When true, `GZip` frames will be added to the compressed data.
   */
  final bool gzip;

  /**
   * The compression-[level] can be set in the range of `-1..9`, with `6` being
   * the default compression level. Levels above `6` will have higher
   * compression rates at the cost of more CPU and memory usage. Levels below
   * `6` will use less CPU and memory at the cost of lower compression rates.
   */
  final int level;

  /**
   * Specifies how much memory should be allocated for the internal compression
   * state. `1` uses minimum memory but is slow and reduces compression ratio;
   * `9` uses maximum memory for optimal speed. The default value is `8`.
   *
   * The memory requirements for deflate are (in bytes):
   *
   *     (1 << (windowBits + 2)) +  (1 << (memLevel + 9))
   * that is: 128K for windowBits = 15 + 128K for memLevel = 8 (default values)
   */
  final int memLevel;

  /**
   * Tunes the compression algorithm. Use the value
   * [ZLibOption.strategyDefault] for normal data,
   * [ZLibOption.strategyFiltered] for data produced by a filter
   * (or predictor), [ZLibOption.strategyHuffmanOnly] to force Huffman
   * encoding only (no string match), or [ZLibOption.strategyRle] to limit
   * match distances to one (run-length encoding).
   */
  final int strategy;

  /**
   * Base two logarithm of the window size (the size of the history buffer). It
   * should be in the range `8..15`. Larger values result in better compression
   * at the expense of memory usage. The default value is `15`
   */
  final int windowBits;

  /**
   * Initial compression dictionary.
   *
   * It should consist of strings (byte sequences) that are likely to be
   * encountered later in the data to be compressed, with the most commonly used
   * strings preferably put towards the end of the dictionary. Using a
   * dictionary is most useful when the data to be compressed is short and can
   * be predicted with good accuracy; the data can then be compressed better
   * than with the default empty dictionary.
   */
  final List<int>? dictionary;

  /**
   * When true, deflate generates raw data with no zlib header or trailer, and
   * will not compute an adler32 check value
   */
  final bool raw;

  GZipCodec(
      {this.level: ZLibOption.defaultLevel,
      this.windowBits: ZLibOption.defaultWindowBits,
      this.memLevel: ZLibOption.defaultMemLevel,
      this.strategy: ZLibOption.strategyDefault,
      this.dictionary,
      this.raw: false,
      this.gzip: true}) {
    _validateZLibeLevel(level);
    _validateZLibMemLevel(memLevel);
    _validateZLibStrategy(strategy);
    _validateZLibWindowBits(windowBits);
  }

  const GZipCodec._default()
      : level = ZLibOption.defaultLevel,
        windowBits = ZLibOption.defaultWindowBits,
        memLevel = ZLibOption.defaultMemLevel,
        strategy = ZLibOption.strategyDefault,
        raw = false,
        gzip = true,
        dictionary = null;

  /**
   * Get a [ZLibEncoder] for encoding to `GZip` compressed data.
   */
  ZLibEncoder get encoder => new ZLibEncoder(
      gzip: true,
      level: level,
      windowBits: windowBits,
      memLevel: memLevel,
      strategy: strategy,
      dictionary: dictionary,
      raw: raw);

  /**
   * Get a [ZLibDecoder] for decoding `GZip` compressed data.
   */
  ZLibDecoder get decoder =>
      new ZLibDecoder(windowBits: windowBits, dictionary: dictionary, raw: raw);
}

/**
 * The [ZLibEncoder] encoder is used by [ZLibCodec] and [GZipCodec] to compress
 * data.
 */
class ZLibEncoder extends Converter<List<int>, List<int>> {
  /**
   * When true, `GZip` frames will be added to the compressed data.
   */
  final bool gzip;

  /**
   * The compression-[level] can be set in the range of `-1..9`, with `6` being
   * the default compression level. Levels above `6` will have higher
   * compression rates at the cost of more CPU and memory usage. Levels below
   * `6` will use less CPU and memory at the cost of lower compression rates.
   */
  final int level;

  /**
   * Specifies how much memory should be allocated for the internal compression
   * state. `1` uses minimum memory but is slow and reduces compression ratio;
   * `9` uses maximum memory for optimal speed. The default value is `8`.
   *
   * The memory requirements for deflate are (in bytes):
   *
   *     (1 << (windowBits + 2)) +  (1 << (memLevel + 9))
   * that is: 128K for windowBits = 15 + 128K for memLevel = 8 (default values)
   */
  final int memLevel;

  /**
   * Tunes the compression algorithm. Use the value
   * [ZLibOption.strategyDefault] for normal data,
   * [ZLibOption.strategyFiltered] for data produced by a filter
   * (or predictor), [ZLibOption.strategyHuffmanOnly] to force Huffman
   * encoding only (no string match), or [ZLibOption.strategyRle] to limit
   * match distances to one (run-length encoding).
   */
  final int strategy;

  /**
   * Base two logarithm of the window size (the size of the history buffer). It
   * should be in the range `8..15`. Larger values result in better compression
   * at the expense of memory usage. The default value is `15`
   */
  final int windowBits;

  /**
   * Initial compression dictionary.
   *
   * It should consist of strings (byte sequences) that are likely to be
   * encountered later in the data to be compressed, with the most commonly used
   * strings preferably put towards the end of the dictionary. Using a
   * dictionary is most useful when the data to be compressed is short and can
   * be predicted with good accuracy; the data can then be compressed better
   * than with the default empty dictionary.
   */
  final List<int>? dictionary;

  /**
   * When true, deflate generates raw data with no zlib header or trailer, and
   * will not compute an adler32 check value
   */
  final bool raw;

  ZLibEncoder(
      {this.gzip: false,
      this.level: ZLibOption.defaultLevel,
      this.windowBits: ZLibOption.defaultWindowBits,
      this.memLevel: ZLibOption.defaultMemLevel,
      this.strategy: ZLibOption.strategyDefault,
      this.dictionary,
      this.raw: false}) {
    _validateZLibeLevel(level);
    _validateZLibMemLevel(memLevel);
    _validateZLibStrategy(strategy);
    _validateZLibWindowBits(windowBits);
  }

  /**
   * Convert a list of bytes using the options given to the ZLibEncoder
   * constructor.
   */
  List<int> convert(List<int> bytes) {
    _BufferSink sink = new _BufferSink();
    startChunkedConversion(sink)
      ..add(bytes)
      ..close();
    return sink.builder.takeBytes();
  }

  /**
   * Start a chunked conversion using the options given to the [ZLibEncoder]
   * constructor. While it accepts any [Sink] taking [List<int>]'s,
   * the optimal sink to be passed as [sink] is a [ByteConversionSink].
   */
  ByteConversionSink startChunkedConversion(Sink<List<int>> sink) {
    if (sink is! ByteConversionSink) {
      sink = new ByteConversionSink.from(sink);
    }
    return new _ZLibEncoderSink._(
        sink, gzip, level, windowBits, memLevel, strategy, dictionary, raw);
  }
}

/**
 * The [ZLibDecoder] is used by [ZLibCodec] and [GZipCodec] to decompress data.
 */
class ZLibDecoder extends Converter<List<int>, List<int>> {
  /**
   * Base two logarithm of the window size (the size of the history buffer). It
   * should be in the range `8..15`. Larger values result in better compression
   * at the expense of memory usage. The default value is `15`.
   */
  final int windowBits;

  /**
   * Initial compression dictionary.
   *
   * It should consist of strings (byte sequences) that are likely to be
   * encountered later in the data to be compressed, with the most commonly used
   * strings preferably put towards the end of the dictionary. Using a
   * dictionary is most useful when the data to be compressed is short and can
   * be predicted with good accuracy; the data can then be compressed better
   * than with the default empty dictionary.
   */
  final List<int>? dictionary;

  /**
   * When true, deflate generates raw data with no zlib header or trailer, and
   * will not compute an adler32 check value
   */
  final bool raw;

  ZLibDecoder(
      {this.windowBits: ZLibOption.defaultWindowBits,
      this.dictionary,
      this.raw: false}) {
    _validateZLibWindowBits(windowBits);
  }

  /**
   * Convert a list of bytes using the options given to the [ZLibDecoder]
   * constructor.
   */
  List<int> convert(List<int> bytes) {
    _BufferSink sink = new _BufferSink();
    startChunkedConversion(sink)
      ..add(bytes)
      ..close();
    return sink.builder.takeBytes();
  }

  /**
   * Start a chunked conversion. While it accepts any [Sink]
   * taking [List<int>]'s, the optimal sink to be passed as [sink] is a
   * [ByteConversionSink].
   */
  ByteConversionSink startChunkedConversion(Sink<List<int>> sink) {
    if (sink is! ByteConversionSink) {
      sink = new ByteConversionSink.from(sink);
    }
    return new _ZLibDecoderSink._(sink, windowBits, dictionary, raw);
  }
}

/**
 * The [RawZLibFilter] class provides a low-level interface to zlib.
 */
abstract class RawZLibFilter {
  /**
   * Returns a a [RawZLibFilter] whose [process] and [processed] methods
   * compress data.
   */
  factory RawZLibFilter.deflateFilter({
    bool gzip: false,
    int level: ZLibOption.defaultLevel,
    int windowBits: ZLibOption.defaultWindowBits,
    int memLevel: ZLibOption.defaultMemLevel,
    int strategy: ZLibOption.strategyDefault,
    List<int>? dictionary,
    bool raw: false,
  }) {
    return _makeZLibDeflateFilter(
        gzip, level, windowBits, memLevel, strategy, dictionary, raw);
  }

  /**
   * Returns a a [RawZLibFilter] whose [process] and [processed] methods
   * decompress data.
   */
  factory RawZLibFilter.inflateFilter({
    int windowBits: ZLibOption.defaultWindowBits,
    List<int>? dictionary,
    bool raw: false,
  }) {
    return _makeZLibInflateFilter(windowBits, dictionary, raw);
  }

  /**
   * Call to process a chunk of data. A call to [process] should only be made
   * when [processed] returns [:null:].
   */
  void process(List<int> data, int start, int end);

  /**
   * Get a chunk of processed data. When there are no more data available,
   * [processed] will return [:null:]. Set [flush] to [:false:] for non-final
   * calls to improve performance of some filters.
   *
   * The last call to [processed] should have [end] set to [:true:]. This will
   * make sure an 'end' packet is written on the stream.
   */
  List<int>? processed({bool flush: true, bool end: false});

  external static RawZLibFilter _makeZLibDeflateFilter(
      bool gzip,
      int level,
      int windowBits,
      int memLevel,
      int strategy,
      List<int>? dictionary,
      bool raw);

  external static RawZLibFilter _makeZLibInflateFilter(
      int windowBits, List<int>? dictionary, bool raw);
}

class _BufferSink extends ByteConversionSink {
  final BytesBuilder builder = new BytesBuilder(copy: false);

  void add(List<int> chunk) {
    builder.add(chunk);
  }

  void addSlice(List<int> chunk, int start, int end, bool isLast) {
    if (chunk is Uint8List) {
      Uint8List list = chunk;
      builder.add(new Uint8List.view(
          list.buffer, list.offsetInBytes + start, end - start));
    } else {
      builder.add(chunk.sublist(start, end));
    }
  }

  void close() {}
}

class _ZLibEncoderSink extends _FilterSink {
  _ZLibEncoderSink._(
      ByteConversionSink sink,
      bool gzip,
      int level,
      int windowBits,
      int memLevel,
      int strategy,
      List<int>? dictionary,
      bool raw)
      : super(
            sink,
            RawZLibFilter._makeZLibDeflateFilter(
                gzip, level, windowBits, memLevel, strategy, dictionary, raw));
}

class _ZLibDecoderSink extends _FilterSink {
  _ZLibDecoderSink._(
      ByteConversionSink sink, int windowBits, List<int>? dictionary, bool raw)
      : super(sink,
            RawZLibFilter._makeZLibInflateFilter(windowBits, dictionary, raw));
}

class _FilterSink extends ByteConversionSink {
  final RawZLibFilter _filter;
  final ByteConversionSink _sink;
  bool _closed = false;
  bool _empty = true;

  _FilterSink(this._sink, this._filter);

  void add(List<int> data) {
    addSlice(data, 0, data.length, false);
  }

  void addSlice(List<int> data, int start, int end, bool isLast) {
    // TODO(40614): Remove once non-nullability is sound.
    ArgumentError.checkNotNull(end, "end");
    if (_closed) return;
    RangeError.checkValidRange(start, end, data.length);
    try {
      _empty = false;
      _BufferAndStart bufferAndStart =
          _ensureFastAndSerializableByteData(data, start, end);
      _filter.process(bufferAndStart.buffer, bufferAndStart.start,
          end - (start - bufferAndStart.start));
      List<int>? out;
      while (true) {
        final out = _filter.processed(flush: false);
        if (out == null) break;
        _sink.add(out);
      }
    } catch (e) {
      _closed = true;
      rethrow;
    }

    if (isLast) close();
  }

  void close() {
    if (_closed) return;
    // Be sure to send process an empty chunk of data. Without this, the empty
    // message would not have a GZip frame (if compressed with GZip).
    if (_empty) _filter.process(const [], 0, 0);
    try {
      while (true) {
        final out = _filter.processed(end: true);
        if (out == null) break;
        _sink.add(out);
      }
    } catch (e) {
      // TODO(kevmoo): not sure why this isn't a try/finally
      _closed = true;
      throw e;
    }
    _closed = true;
    _sink.close();
  }
}

void _validateZLibWindowBits(int windowBits) {
  if (ZLibOption.minWindowBits > windowBits ||
      ZLibOption.maxWindowBits < windowBits) {
    throw new RangeError.range(
        windowBits, ZLibOption.minWindowBits, ZLibOption.maxWindowBits);
  }
}

void _validateZLibeLevel(int level) {
  if (ZLibOption.minLevel > level || ZLibOption.maxLevel < level) {
    throw new RangeError.range(level, ZLibOption.minLevel, ZLibOption.maxLevel);
  }
}

void _validateZLibMemLevel(int memLevel) {
  if (ZLibOption.minMemLevel > memLevel || ZLibOption.maxMemLevel < memLevel) {
    throw new RangeError.range(
        memLevel, ZLibOption.minMemLevel, ZLibOption.maxMemLevel);
  }
}

void _validateZLibStrategy(int strategy) {
  const strategies = const <int>[
    ZLibOption.strategyFiltered,
    ZLibOption.strategyHuffmanOnly,
    ZLibOption.strategyRle,
    ZLibOption.strategyFixed,
    ZLibOption.strategyDefault
  ];
  if (strategies.indexOf(strategy) == -1) {
    throw new ArgumentError("Unsupported 'strategy'");
  }
}
