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

library convert.percent.decoder;

import 'dart:convert';

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

import '../utils.dart';

/// The canonical instance of [PercentDecoder].
const percentDecoder = PercentDecoder._();

const _lastPercent = -1;

/// A converter that decodes percent-encoded strings into byte arrays.
///
/// To be maximally flexible, this will decode any percent-encoded byte and
/// will allow any non-percent-encoded byte other than `%`. By default, it
/// interprets `+` as `0x2B` rather than `0x20` as emitted by
/// [Uri.encodeQueryComponent].
///
/// This will throw a [FormatException] if the input string has an incomplete
/// percent-encoding, or if it contains non-ASCII code units.
class PercentDecoder extends Converter<String, List<int>> {
  const PercentDecoder._();

  List<int> convert(String string) {
    var buffer = Uint8Buffer();
    var lastDigit = _decode(string.codeUnits, 0, string.length, buffer);

    if (lastDigit != null) {
      throw FormatException(
          "Input ended with incomplete encoded byte.", string, string.length);
    }

    return buffer.buffer.asUint8List(0, buffer.length);
  }

  StringConversionSink startChunkedConversion(Sink<List<int>> sink) =>
      _PercentDecoderSink(sink);
}

/// A conversion sink for chunked percent-encoded decoding.
class _PercentDecoderSink extends StringConversionSinkBase {
  /// The underlying sink to which decoded byte arrays will be passed.
  final Sink<List<int>> _sink;

  /// The trailing digit from the previous string.
  ///
  /// This is `null` if the previous string ended with a complete
  /// percent-encoded byte or a literal character. It's [_lastPercent] if the
  /// most recent string ended with `%`. Otherwise, the most recent string ended
  /// with a `%` followed by a hexadecimal digit, and this is that digit. Since
  /// it's the most significant digit, it's always a multiple of 16.
  int _lastDigit;

  _PercentDecoderSink(this._sink);

  void addSlice(String string, int start, int end, bool isLast) {
    RangeError.checkValidRange(start, end, string.length);

    if (start == end) {
      if (isLast) _close(string, end);
      return;
    }

    var buffer = Uint8Buffer();
    var codeUnits = string.codeUnits;
    if (_lastDigit == _lastPercent) {
      _lastDigit = 16 * digitForCodeUnit(codeUnits, start);
      start++;

      if (start == end) {
        if (isLast) _close(string, end);
        return;
      }
    }

    if (_lastDigit != null) {
      buffer.add(_lastDigit + digitForCodeUnit(codeUnits, start));
      start++;
    }

    _lastDigit = _decode(codeUnits, start, end, buffer);

    _sink.add(buffer.buffer.asUint8List(0, buffer.length));
    if (isLast) _close(string, end);
  }

  ByteConversionSink asUtf8Sink(bool allowMalformed) =>
      _PercentDecoderByteSink(_sink);

  void close() => _close();

  /// Like [close], but includes [string] and [index] in the [FormatException]
  /// if one is thrown.
  void _close([String string, int index]) {
    if (_lastDigit != null) {
      throw FormatException(
          "Input ended with incomplete encoded byte.", string, index);
    }

    _sink.close();
  }
}

/// A conversion sink for chunked percent-encoded decoding from UTF-8 bytes.
class _PercentDecoderByteSink extends ByteConversionSinkBase {
  /// The underlying sink to which decoded byte arrays will be passed.
  final Sink<List<int>> _sink;

  /// The trailing digit from the previous string.
  ///
  /// This is `null` if the previous string ended with a complete
  /// percent-encoded byte or a literal character. It's [_lastPercent] if the
  /// most recent string ended with `%`. Otherwise, the most recent string ended
  /// with a `%` followed by a hexadecimal digit, and this is that digit. Since
  /// it's the most significant digit, it's always a multiple of 16.
  int _lastDigit;

  _PercentDecoderByteSink(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);

    if (start == end) {
      if (isLast) _close(chunk, end);
      return;
    }

    var buffer = Uint8Buffer();
    if (_lastDigit == _lastPercent) {
      _lastDigit = 16 * digitForCodeUnit(chunk, start);
      start++;

      if (start == end) {
        if (isLast) _close(chunk, end);
        return;
      }
    }

    if (_lastDigit != null) {
      buffer.add(_lastDigit + digitForCodeUnit(chunk, start));
      start++;
    }

    _lastDigit = _decode(chunk, start, end, buffer);

    _sink.add(buffer.buffer.asUint8List(0, buffer.length));
    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 (_lastDigit != null) {
      throw FormatException(
          "Input ended with incomplete encoded byte.", chunk, index);
    }

    _sink.close();
  }
}

/// Decodes [codeUnits] and writes the result into [destination].
///
/// This reads from [codeUnits] between [sourceStart] and [sourceEnd]. It writes
/// the result into [destination] starting at [destinationStart].
///
/// If there's a leftover digit at the end of the decoding, this returns that
/// digit. Otherwise it returns `null`.
int _decode(List<int> codeUnits, int start, int end, Uint8Buffer buffer) {
  // A bitwise OR of all code units in [codeUnits]. This allows us to check for
  // out-of-range code units without adding more branches than necessary to the
  // core loop.
  var codeUnitOr = 0;

  // The beginning of the current slice of adjacent non-% characters. We can add
  // all of these to the buffer at once.
  var sliceStart = start;
  for (var i = start; i < end; i++) {
    // First, loop through non-% characters.
    var codeUnit = codeUnits[i];
    if (codeUnits[i] != $percent) {
      codeUnitOr |= codeUnit;
      continue;
    }

    // We found a %. The slice from `sliceStart` to `i` represents characters
    // than can be copied to the buffer as-is.
    if (i > sliceStart) {
      _checkForInvalidCodeUnit(codeUnitOr, codeUnits, sliceStart, i);
      buffer.addAll(codeUnits, sliceStart, i);
    }

    // Now decode the percent-encoded byte and add it as well.
    i++;
    if (i >= end) return _lastPercent;

    var firstDigit = digitForCodeUnit(codeUnits, i);
    i++;
    if (i >= end) return 16 * firstDigit;

    var secondDigit = digitForCodeUnit(codeUnits, i);
    buffer.add(16 * firstDigit + secondDigit);

    // The next iteration will look for non-% characters again.
    sliceStart = i + 1;
  }

  if (end > sliceStart) {
    _checkForInvalidCodeUnit(codeUnitOr, codeUnits, sliceStart, end);
    if (start == sliceStart) {
      buffer.addAll(codeUnits);
    } else {
      buffer.addAll(codeUnits, sliceStart, end);
    }
  }

  return null;
}

void _checkForInvalidCodeUnit(
    int codeUnitOr, List<int> codeUnits, int start, int end) {
  if (codeUnitOr >= 0 && codeUnitOr <= 0x7f) return;

  for (var i = start; i < end; i++) {
    var codeUnit = codeUnits[i];
    if (codeUnit >= 0 && codeUnit <= 0x7f) continue;
    throw FormatException(
        "Non-ASCII code unit "
        "U+${codeUnit.toRadixString(16).padLeft(4, '0')}",
        codeUnits,
        i);
  }
}
