// Copyright (c) 2012, 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.

// Interface for decoders decoding binary data into string data. The
// decoder keeps track of line breaks during decoding.
abstract class _StringDecoder {
  // Add more binary data to be decoded. The ownership of the buffer
  // is transfered to the decoder and the caller most not modify it any more.
  int write(List<int> buffer);

  // Returns whether any decoded data is available.
  bool isEmpty();

  // Returns the number of available decoded characters.
  int available();

  // Get the number of line breaks present in the current decoded
  // data.
  int get lineBreaks;

  // Get up to [len] characters of string data decoded since the last
  // call to [decode] or [decodeLine]. Returns null if no decoded data
  // is available. If [len] is not specified all decoded characters
  // are returned.
  String decoded([int len]);

  // Get the string data decoded since the last call to [decode] or
  // [decodeLine] up to the next line break present. Returns null if
  // no line break is present. The line break character sequence is
  // discarded.
  String get decodedLine;
}


class _StringDecoders {
  static _StringDecoder decoder(Encoding encoding) {
    if (encoding == Encoding.UTF_8) {
      return new _UTF8Decoder();
    } else if (encoding == Encoding.ISO_8859_1) {
      return new _Latin1Decoder();
    } else if (encoding == Encoding.ASCII) {
      return new _AsciiDecoder();
    } else {
      if (encoding is Encoding) {
        throw new StreamException("Unsupported encoding ${encoding.name}");
      } else {
        throw new StreamException("Unsupported encoding ${encoding}");
      }
    }
  }
}


class DecoderException implements Exception {
  const DecoderException([String this.message]);
  String toString() => "DecoderException: $message";
  final String message;
}


// Utility class for decoding UTF-8 from data delivered as a stream of
// bytes.
class _StringDecoderBase implements _StringDecoder {
  _StringDecoderBase()
      : _bufferList = new _BufferList(),
        _result = new List<int>(),
        _lineBreakEnds = new Queue<int>();

  int write(List<int> buffer) {
    _bufferList.add(buffer);
    // Decode as many bytes into characters as possible.
    while (_bufferList.length > 0) {
      if (!_processNext()) {
        break;
      }
    }
    return buffer.length;
  }

  bool isEmpty() => _result.isEmpty();

  int get lineBreaks => _lineBreaks;

  String decoded([int len]) {
    if (isEmpty()) return null;

    String result;
    if (len !== null && len < available()) {
      result = new String.fromCharCodes(_result.getRange(_resultOffset, len));
    } else {
      if (_resultOffset == 0) {
        result = new String.fromCharCodes(_result);
      } else {
        result =
            new String.fromCharCodes(
                _result.getRange(_resultOffset,
                                 _result.length - _resultOffset));
      }
    }
    _resultOffset += result.length;
    while (!_lineBreakEnds.isEmpty() &&
           _lineBreakEnds.first() < _charOffset + _resultOffset) {
      _lineBreakEnds.removeFirst();
      _lineBreaks--;
    }
    if (_result.length == _resultOffset) _resetResult();
    return result;
  }

  String get decodedLine {
    if (_lineBreakEnds.isEmpty()) return null;
    int lineEnd = _lineBreakEnds.removeFirst();
    int terminationSequenceLength = 1;
    if (_result[lineEnd - _charOffset] == LF &&
        lineEnd > _charOffset &&
        _resultOffset < lineEnd &&
        _result[lineEnd - _charOffset - 1] == CR) {
      terminationSequenceLength = 2;
    }
    var lineLength =
        lineEnd - _charOffset - _resultOffset - terminationSequenceLength + 1;
    String result =
        new String.fromCharCodes(_result.getRange(_resultOffset, lineLength));
    _lineBreaks--;
    _resultOffset += (lineLength + terminationSequenceLength);
    if (_result.length == _resultOffset) _resetResult();
    return result;
  }

  // Add another decoded character.
  void addChar(int charCode) {
    _result.add(charCode);
    _charCount++;
    // Check for line ends (\r, \n and \r\n).
    if (charCode == LF) {
      _recordLineBreakEnd(_charCount - 1);
    } else if (_lastCharCode == CR) {
      _recordLineBreakEnd(_charCount - 2);
    }
    _lastCharCode = charCode;
  }

  int available() => _result.length - _resultOffset;

  void _recordLineBreakEnd(int charPos) {
    _lineBreakEnds.add(charPos);
    _lineBreaks++;
  }

  void _resetResult() {
    _charOffset += _result.length;
    _result = new List<int>();
    _resultOffset = 0;
  }

  abstract bool _processNext();

  _BufferList _bufferList;
  int _resultOffset = 0;
  List<int> _result;
  int _lineBreaks = 0;  // Number of line breaks in the current list.
  // The positions of the line breaks are tracked in terms of absolute
  // character positions from the begining of the decoded data.
  Queue<int> _lineBreakEnds;  // Character position of known line breaks.
  int _charOffset = 0;  // Character number of the first character in the list.
  int _charCount = 0;  // Total number of characters decoded.
  int _lastCharCode = -1;

  final int LF = 10;
  final int CR = 13;
}


// Utility class for decoding UTF-8 from data delivered as a stream of
// bytes.
class _UTF8Decoder extends _StringDecoderBase {
  // Process the next UTF-8 encoded character.
  bool _processNext() {
    // Peek the next byte to calculate the number of bytes required for
    // the next character.
    int value = _bufferList.peek() & 0xFF;
    if ((value & 0x80) == 0x80) {
      int additionalBytes;
      if ((value & 0xe0) == 0xc0) {  // 110xxxxx
        value = value & 0x1F;
        additionalBytes = 1;
      } else if ((value & 0xf0) == 0xe0) {  // 1110xxxx
        value = value & 0x0F;
        additionalBytes = 2;
      } else {  // 11110xxx
        value = value & 0x07;
        additionalBytes = 3;
      }
      // Check if there are enough bytes to decode the character. Otherwise
      // return false.
      if (_bufferList.length < additionalBytes + 1) {
        return false;
      }
      // Remove the value peeked from the buffer list.
      _bufferList.next();
      for (int i = 0; i < additionalBytes; i++) {
        int byte = _bufferList.next();
        value = value << 6 | (byte & 0x3F);
      }
    } else {
      // Remove the value peeked from the buffer list.
      _bufferList.next();
    }
    addChar(value);
    return true;
  }
}


// Utility class for decoding ascii data delivered as a stream of
// bytes.
class _AsciiDecoder extends _StringDecoderBase {
  // Process the next ascii encoded character.
  bool _processNext() {
    while (_bufferList.length > 0) {
      int byte = _bufferList.next();
      if (byte > 127) {
        throw new DecoderException("Illegal ASCII character $byte");
      }
      addChar(byte);
    }
    return true;
  }
}


// Utility class for decoding Latin-1 data delivered as a stream of
// bytes.
class _Latin1Decoder extends _StringDecoderBase {
  // Process the next Latin-1 encoded character.
  bool _processNext() {
    while (_bufferList.length > 0) {
      int byte = _bufferList.next();
      addChar(byte);
    }
    return true;
  }
}


// Interface for encoders encoding string data into binary data.
abstract class _StringEncoder {
  List<int> encodeString(String string);
}


// Utility class for encoding a string into UTF-8 byte stream.
class _UTF8Encoder implements _StringEncoder {
  List<int> encodeString(String string) {
    int size = _encodingSize(string);
    List<int> result = new Uint8List(size);
    _encodeString(string, result);
    return result;
  }

  static int _encodingSize(String string) => _encodeString(string, null);

  static int _encodeString(String string, List<int> buffer) {
    int pos = 0;
    int length = string.length;
    for (int i = 0; i < length; i++) {
      int additionalBytes;
      int charCode = string.charCodeAt(i);
      if (charCode <= 0x007F) {
        additionalBytes = 0;
        if (buffer != null) buffer[pos] = charCode;
      } else if (charCode <= 0x07FF) {
        // 110xxxxx (xxxxx is top 5 bits).
        if (buffer != null) buffer[pos] = ((charCode >> 6) & 0x1F) | 0xC0;
        additionalBytes = 1;
      } else if (charCode <= 0xFFFF) {
        // 1110xxxx (xxxx is top 4 bits)
        if (buffer != null) buffer[pos] = ((charCode >> 12) & 0x0F)| 0xE0;
        additionalBytes = 2;
      } else {
        // 11110xxx (xxx is top 3 bits)
        if (buffer != null) buffer[pos] = ((charCode >> 18) & 0x07) | 0xF0;
        additionalBytes = 3;
      }
      pos++;
      if (buffer != null) {
        for (int i = additionalBytes; i > 0; i--) {
          // 10xxxxxx (xxxxxx is next 6 bits from the top).
          buffer[pos++] = ((charCode >> (6 * (i - 1))) & 0x3F) | 0x80;
        }
      } else {
        pos += additionalBytes;
      }
    }
    return pos;
  }
}


// Utility class for encoding a string into a Latin1 byte stream.
class _Latin1Encoder implements _StringEncoder {
  List<int> encodeString(String string) {
    List<int> result = new Uint8List(string.length);
    for (int i = 0; i < string.length; i++) {
      int charCode = string.charCodeAt(i);
      if (charCode > 255) {
        throw new EncoderException(
            "No ISO_8859_1 encoding for code point $charCode");
      }
      result[i] = charCode;
    }
    return result;
  }
}


// Utility class for encoding a string into an ASCII byte stream.
class _AsciiEncoder implements _StringEncoder {
  List<int> encodeString(String string) {
    List<int> result = new Uint8List(string.length);
    for (int i = 0; i < string.length; i++) {
      int charCode = string.charCodeAt(i);
      if (charCode > 127) {
        throw new EncoderException(
            "No ASCII encoding for code point $charCode");
      }
      result[i] = charCode;
    }
    return result;
  }
}


class _StringEncoders {
  static _StringEncoder encoder(Encoding encoding) {
    if (encoding == Encoding.UTF_8) {
      return new _UTF8Encoder();
    } else if (encoding == Encoding.ISO_8859_1) {
      return new _Latin1Encoder();
    } else if (encoding == Encoding.ASCII) {
      return new _AsciiEncoder();
    } else {
      throw new StreamException("Unsupported encoding ${encoding.name}");
    }
  }
}


class EncoderException implements Exception {
  const EncoderException([String this.message]);
  String toString() => "EncoderException: $message";
  final String message;
}


class _StringInputStream implements StringInputStream {
  _StringInputStream(InputStream this._input, Encoding this._encoding) {
    _decoder = _StringDecoders.decoder(encoding);
    _input.onData = _onData;
    _input.onClosed = _onClosed;
  }

  String read([int len]) {
    String result = _decoder.decoded(len);
    _checkInstallDataHandler();
    return result;
  }

  String readLine() {
    String decodedLine = _decoder.decodedLine;
    if (decodedLine == null) {
      if (_inputClosed) {
        // Last line might not have a line separator.
        decodedLine = _decoder.decoded();
        if (decodedLine != null &&
            decodedLine[decodedLine.length - 1] == '\r') {
          decodedLine = decodedLine.substring(0, decodedLine.length - 1);
        }
      }
    }
    _checkInstallDataHandler();
    return decodedLine;
  }

  int available() => _decoder.available();

  Encoding get encoding => _encoding;

  bool get closed => _inputClosed && _decoder.isEmpty();

  void set onData(void callback()) {
    _clientDataHandler = callback;
    _clientLineHandler = null;
    _checkInstallDataHandler();
    _checkScheduleCallback();
  }

  void set onLine(void callback()) {
    _clientLineHandler = callback;
    _clientDataHandler = null;
    _checkInstallDataHandler();
    _checkScheduleCallback();
  }

  void set onClosed(void callback()) {
    _clientCloseHandler = callback;
  }

  void set onError(void callback(e)) {
    _input.onError = callback;
  }

  void _onData() {
    _readData();
    if (!_decoder.isEmpty() && _clientDataHandler !== null) {
      _clientDataHandler();
    }
    if (_decoder.lineBreaks > 0 && _clientLineHandler !== null) {
      _clientLineHandler();
    }
    _checkScheduleCallback();
    _checkInstallDataHandler();
  }

  void _onClosed() {
    _inputClosed = true;
    if (_decoder.isEmpty() && _clientCloseHandler != null) {
      _clientCloseHandler();
      _closed = true;
    } else {
      _checkScheduleCallback();
    }
  }

  void _readData() {
    List<int> data = _input.read();
    if (data !== null) {
      _decoder.write(data);
    }
  }

  void _checkInstallDataHandler() {
    if (_inputClosed ||
        (_clientDataHandler === null && _clientLineHandler === null)) {
      _input.onData = null;
    } else if (_clientDataHandler !== null) {
      if (_decoder.isEmpty()) {
        _input.onData = _onData;
      } else {
        _input.onData = null;
      }
    } else {
      assert(_clientLineHandler !== null);
      if (_decoder.lineBreaks == 0) {
        _input.onData = _onData;
      } else {
        _input.onData = null;
      }
    }
  }

  // TODO(sgjesse): Find a better way of scheduling callbacks from
  // the event loop.
  void _checkScheduleCallback() {
    void issueDataCallback(Timer timer) {
      _scheduledDataCallback = null;
      if (_clientDataHandler !== null) {
        _clientDataHandler();
        _checkScheduleCallback();
      }
    }

    void issueLineCallback(Timer timer) {
      _scheduledLineCallback = null;
      if (_clientLineHandler !== null) {
        _clientLineHandler();
        _checkScheduleCallback();
      }
    }

    void issueCloseCallback(Timer timer) {
      _scheduledCloseCallback = null;
      if (!_closed) {
        if (_clientCloseHandler !== null) _clientCloseHandler();
        _closed = true;
      }
    }

    if (!_closed) {
      // Schedule data callback if string data available.
      if (_clientDataHandler != null &&
          !_decoder.isEmpty() &&
          _scheduledDataCallback == null) {
        if (_scheduledLineCallback != null) {
          _scheduledLineCallback.cancel();
        }
        _scheduledDataCallback = new Timer(0, issueDataCallback);
      }

      // Schedule line callback if a line is available.
      if (_clientLineHandler != null &&
          (_decoder.lineBreaks > 0 || (!_decoder.isEmpty() && _inputClosed)) &&
          _scheduledLineCallback == null) {
        if (_scheduledDataCallback != null) {
          _scheduledDataCallback.cancel();
        }
        _scheduledLineCallback = new Timer(0, issueLineCallback);
      }

      // Schedule close callback if no more data and input is closed.
      if (_decoder.isEmpty() &&
          _inputClosed &&
          _scheduledCloseCallback == null) {
        _scheduledCloseCallback = new Timer(0, issueCloseCallback);
      }
    }
  }

  InputStream _input;
  Encoding _encoding;
  _StringDecoder _decoder;
  bool _inputClosed = false;  // Is the underlying input stream closed?
  bool _closed = false;  // Is this stream closed.
  bool _eof = false;  // Has all data been read from the decoder?
  Timer _scheduledDataCallback;
  Timer _scheduledLineCallback;
  Timer _scheduledCloseCallback;
  Function _clientDataHandler;
  Function _clientLineHandler;
  Function _clientCloseHandler;
}
