// 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:typed_data';

import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart';

/**
 * An instance of [ApiSignature] collects data in the form of primitive types
 * (strings, ints, bools, etc.) from a summary "builder" object, and uses them
 * to generate an MD5 signature of a the non-informative parts of the summary
 * (i.e. those parts representing the API of the code being summarized).
 *
 * Note that the data passed to the MD5 signature algorithm is untyped.  So, for
 * instance, an API signature built from a sequence of `false` booleans is
 * likely to match an API signature built from a sequence of zeros.  The caller
 * should take this into account; e.g. if a data structure may be represented
 * either by a boolean or an int, the caller should encode a tag distinguishing
 * the two representations before encoding the data.
 */
class ApiSignature {
  /**
   * Version number of the code in this class.  Any time this class is changed
   * in a way that affects the data collected in [_data], this version number
   * should be incremented, so that a summary signed by a newer version of the
   * signature algorithm won't accidentally have the same signature as a summary
   * signed by an older version.
   */
  static const int _VERSION = 0;

  /**
   * Data accumulated so far.
   */
  ByteData _data = new ByteData(4096);

  /**
   * Offset into [_data] where the next byte should be written.
   */
  int _offset = 0;

  /**
   * Create an [ApiSignature] which is ready to accept data.
   */
  ApiSignature() {
    addInt(_VERSION);
  }

  /**
   * For testing only: create an [ApiSignature] which doesn't include any
   * version information.  This makes it easier to unit tests, since the data
   * is stable even if [_VERSION] is changed.
   */
  ApiSignature.unversioned();

  /**
   * Collect a boolean value.
   */
  void addBool(bool b) {
    _makeRoom(1);
    _data.setUint8(_offset, b ? 1 : 0);
    _offset++;
  }

  /**
   * Collect a sequence of arbitrary bytes.  Note that the length is not
   * collected, so for example `addBytes([1, 2]);` will have the same effect as
   * `addBytes([1]); addBytes([2]);`.
   */
  void addBytes(List<int> bytes) {
    int length = bytes.length;
    _makeRoom(length);
    for (int i = 0; i < length; i++) {
      _data.setUint8(_offset + i, bytes[i]);
    }
    _offset += length;
  }

  /**
   * Collect a double-precision floating point value.
   */
  void addDouble(double d) {
    _makeRoom(8);
    _data.setFloat64(_offset, d, Endian.little);
    _offset += 8;
  }

  /**
   * Collect a 32-bit unsigned integer value.
   */
  void addInt(int i) {
    _makeRoom(4);
    _data.setUint32(_offset, i, Endian.little);
    _offset += 4;
  }

  /**
   * Collect a string.
   */
  void addString(String s) {
    List<int> bytes = utf8.encode(s);
    addInt(bytes.length);
    addBytes(bytes);
  }

  /**
   * Collect the given [Uint32List].
   */
  void addUint32List(Uint32List data) {
    addBytes(data.buffer.asUint8List());
  }

  /**
   * For testing only: retrieve the internal representation of the data that
   * has been collected.
   */
  List<int> getBytes_forDebug() {
    return new Uint8List.view(_data.buffer, 0, _offset).toList();
  }

  /**
   * Return the bytes of the MD5 hash of the data collected so far.
   */
  List<int> toByteList() {
    return md5.convert(new Uint8List.view(_data.buffer, 0, _offset)).bytes;
  }

  /**
   * Return a hex-encoded MD5 signature of the data collected so far.
   */
  String toHex() {
    return hex.encode(toByteList());
  }

  /**
   * Ensure that [spaceNeeded] bytes can be added to [_data] at [_offset]
   * (copying it to a larger object if necessary).
   */
  void _makeRoom(int spaceNeeded) {
    int oldLength = _data.lengthInBytes;
    if (_offset + spaceNeeded > oldLength) {
      int newLength = 2 * (_offset + spaceNeeded);
      ByteData newData = new ByteData(newLength);
      new Uint8List.view(newData.buffer)
          .setRange(0, oldLength, new Uint8List.view(_data.buffer));
      _data = newData;
    }
  }
}
