// Copyright (c) 2016, 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:convert';
import 'dart:math' as math;
import 'dart:typed_data';

import 'package:charcode/ascii.dart';
import 'package:typed_data/typed_data.dart';

/// The canonical instance of [ChunkedCodingDecoder].
const chunkedCodingDecoder = const ChunkedCodingDecoder._();

/// A converter that decodes byte arrays into chunks with size tags.
class ChunkedCodingDecoder extends Converter<List<int>, List<int>> {
  const ChunkedCodingDecoder._();

  List<int> convert(List<int> bytes) {
    var sink = new _Sink(null);
    var output = sink._decode(bytes, 0, bytes.length);
    if (sink._state == _State.end) return output;

    throw new FormatException("Input ended unexpectedly.", bytes, bytes.length);
  }

  ByteConversionSink startChunkedConversion(Sink<List<int>> sink) =>
      new _Sink(sink);
}

/// A conversion sink for the chunked transfer encoding.
class _Sink extends ByteConversionSinkBase {
  /// The underlying sink to which decoded byte arrays will be passed.
  final Sink<List<int>> _sink;

  /// The current state of the sink's parsing.
  var _state = _State.boundary;

  /// The size of the chunk being parsed, or `null` if the size hasn't been
  /// parsed yet.
  int _size;

  _Sink(this._sink);

  void add(List<int> chunk) => addSlice(chunk, 0, chunk.length, false);

  void addSlice(List<int> chunk, int start, int end, bool isLast) {
    RangeError.checkValidRange(start, end, chunk.length);
    var output = _decode(chunk, start, end);
    if (output.isNotEmpty) _sink.add(output);
    if (isLast) _close(chunk, end);
  }

  void close() => _close();

  /// Like [close], but includes [chunk] and [index] in the [FormatException] if
  /// one is thrown.
  void _close([List<int> chunk, int index]) {
    if (_state != _State.end) {
      throw new FormatException("Input ended unexpectedly.", chunk, index);
    }

    _sink.close();
  }

  /// Decodes the data in [bytes] from [start] to [end].
  Uint8List _decode(List<int> bytes, int start, int end) {
    /// Throws a [FormatException] if `bytes[start] != $char`. Uses [name] to
    /// describe the character in the exception text.
    assertCurrentChar(int char, String name) {
      if (bytes[start] != char) {
        throw new FormatException("Expected $name.", bytes, start);
      }
    }

    var buffer = new Uint8Buffer();
    while (start != end) {
      switch (_state) {
        case _State.boundary:
          _size = _digitForByte(bytes, start);
          _state = _State.size;
          start++;
          break;

        case _State.size:
          if (bytes[start] == $cr) {
            _state = _State.sizeBeforeLF;
          } else {
            // Shift four bits left since a single hex digit contains four bits
            // of information.
            _size = (_size << 4) + _digitForByte(bytes, start);
          }
          start++;
          break;

        case _State.sizeBeforeLF:
          assertCurrentChar($lf, "LF");
          _state = _size == 0 ? _State.endBeforeCR : _State.body;
          start++;
          break;

        case _State.body:
          var chunkEnd = math.min(end, start + _size);
          buffer.addAll(bytes, start, chunkEnd);
          _size -= chunkEnd - start;
          start = chunkEnd;
          if (_size == 0) _state = _State.bodyBeforeCR;
          break;

        case _State.bodyBeforeCR:
          assertCurrentChar($cr, "CR");
          _state = _State.bodyBeforeLF;
          start++;
          break;

        case _State.bodyBeforeLF:
          assertCurrentChar($lf, "LF");
          _state = _State.boundary;
          start++;
          break;

        case _State.endBeforeCR:
          assertCurrentChar($cr, "CR");
          _state = _State.endBeforeLF;
          start++;
          break;

        case _State.endBeforeLF:
          assertCurrentChar($lf, "LF");
          _state = _State.end;
          start++;
          break;

        case _State.end:
          throw new FormatException("Expected no more data.", bytes, start);
      }
    }
    return buffer.buffer.asUint8List(0, buffer.length);
  }

  /// Returns the hex digit (0 through 15) corresponding to the byte at index
  /// [i] in [bytes].
  ///
  /// If the given byte isn't a hexadecimal ASCII character, throws a
  /// [FormatException].
  int _digitForByte(List<int> bytes, int index) {
    // If the byte is a numeral, get its value. XOR works because 0 in ASCII is
    // `0b110000` and the other numerals come after it in ascending order and
    // take up at most four bits.
    //
    // We check for digits first because it ensures there's only a single branch
    // for 10 out of 16 of the expected cases. We don't count the `digit >= 0`
    // check because branch prediction will always work on it for valid data.
    var byte = bytes[index];
    var digit = $0 ^ byte;
    if (digit <= 9) {
      if (digit >= 0) return digit;
    } else {
      // If the byte is an uppercase letter, convert it to lowercase. This works
      // because uppercase letters in ASCII are exactly `0b100000 = 0x20` less
      // than lowercase letters, so if we ensure that that bit is 1 we ensure that
      // the letter is lowercase.
      var letter = 0x20 | byte;
      if ($a <= letter && letter <= $f) return letter - $a + 10;
    }

    throw new FormatException(
        "Invalid hexadecimal byte 0x${byte.toRadixString(16).toUpperCase()}.",
        bytes,
        index);
  }
}

/// An enumeration of states that [_Sink] can exist in when decoded a chunked
/// message.
class _State {
  /// The parser has fully parsed one chunk and is expecting the header for the
  /// next chunk.
  ///
  /// Transitions to [size].
  static const boundary = const _State._("boundary");

  /// The parser has parsed at least one digit of the chunk size header, but has
  /// not yet parsed the `CR LF` sequence that indicates the end of that header.
  ///
  /// Transitions to [sizeBeforeLF].
  static const size = const _State._("size");

  /// The parser has parsed the chunk size header and the CR character after it,
  /// but not the LF.
  ///
  /// Transitions to [body] or [bodyBeforeCR].
  static const sizeBeforeLF = const _State._("size before LF");

  /// The parser has parsed a chunk header and possibly some of the body, but
  /// still needs to consume more bytes.
  ///
  /// Transitions to [bodyBeforeCR].
  static const body = const _State._("body");

  // The parser has parsed all the bytes in a chunk body but not the CR LF
  // sequence that follows it.
  //
  // Transitions to [bodyBeforeLF].
  static const bodyBeforeCR = const _State._("body before CR");

  // The parser has parsed all the bytes in a chunk body and the CR that follows
  // it, but not the LF after that.
  //
  // Transitions to [bounday].
  static const bodyBeforeLF = const _State._("body before LF");

  /// The parser has parsed the final empty chunk but not the CR LF sequence
  /// that follows it.
  ///
  /// Transitions to [endBeforeLF].
  static const endBeforeCR = const _State._("end before CR");

  /// The parser has parsed the final empty chunk and the CR that follows it,
  /// but not the LF after that.
  ///
  /// Transitions to [end].
  static const endBeforeLF = const _State._("end before LF");

  /// The parser has parsed the final empty chunk as well as the CR LF that
  /// follows, and expects no more data.
  static const end = const _State._("end");

  final String _name;

  const _State._(this._name);

  String toString() => _name;
}
