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

import 'dart:collection';

import 'package:front_end/src/fasta/scanner/characters.dart';

/**
 * The [DartString] type represents a Dart string value as a sequence of Unicode
 * Scalar Values.
 * After parsing, any valid [LiteralString] will contain a [DartString]
 * representing its content after removing quotes and resolving escapes in
 * its source.
 */
abstract class DartString extends IterableBase<int> {
  factory DartString.empty() => const LiteralDartString("");
  // This is a convenience constructor. If you need a const literal DartString,
  // use [const LiteralDartString(string)] directly.
  factory DartString.literal(String string) => new LiteralDartString(string);
  factory DartString.rawString(String source, int length) =>
      new RawSourceDartString(source, length);
  factory DartString.escapedString(String source, int length) =>
      new EscapedSourceDartString(source, length);
  factory DartString.concat(DartString first, DartString second) {
    if (first.isEmpty) return second;
    if (second.isEmpty) return first;
    return new ConsDartString(first, second);
  }
  const DartString();

  /**
   * The length of this [DartString], which is the string length after
   * escapes have been resolved.
   */
  int get length;
  bool get isEmpty => length == 0;

  Iterator<int> get iterator;

  /**
   * The string represented by this [DartString].
   */
  String slowToString();

  bool operator ==(var other) {
    if (other is! DartString) return false;
    DartString otherString = other;
    if (length != otherString.length) return false;
    Iterator it1 = iterator;
    Iterator it2 = otherString.iterator;
    while (it1.moveNext()) {
      if (!it2.moveNext()) return false;
      if (it1.current != it2.current) return false;
    }
    return true;
  }

  int get hashCode => throw new UnsupportedError('DartString.hashCode');

  /**
   * A textual representation of this [DartString] with some debugging
   * information.
   */
  String toString() => "DartString#${length}:${slowToString()}";
}

/**
 * A [DartString] where the content is represented by an actual [String].
 */
class LiteralDartString extends DartString {
  final String string;
  const LiteralDartString(this.string);
  int get length => string.length;
  Iterator<int> get iterator => string.codeUnits.iterator;
  String slowToString() => string;
}

/**
 * A [DartString] whereSource the content comes from a slice of the program
 * source.
 */
abstract class SourceBasedDartString extends DartString {
  /**
   * The source string containing explicit escapes from which this [DartString]
   * is built.
   */
  final String source;
  final int length;
  SourceBasedDartString(this.source, this.length);
  Iterator<int> get iterator;
}

/**
 * Special case of a [SourceBasedDartString] where we know the source doesn't
 * contain any escapes.
 */
class RawSourceDartString extends SourceBasedDartString {
  RawSourceDartString(source, length) : super(source, length);
  Iterator<int> get iterator => source.codeUnits.iterator;
  String slowToString() => source;
}

/**
 * General case of a [SourceBasedDartString] where the source might contain
 * escapes.
 */
class EscapedSourceDartString extends SourceBasedDartString {
  String toStringCache;
  EscapedSourceDartString(source, length) : super(source, length);
  Iterator<int> get iterator {
    if (toStringCache != null) return toStringCache.codeUnits.iterator;
    return new StringEscapeIterator(source);
  }

  String slowToString() {
    if (toStringCache != null) return toStringCache;
    StringBuffer buffer = new StringBuffer();
    StringEscapeIterator it = new StringEscapeIterator(source);
    while (it.moveNext()) {
      buffer.writeCharCode(it.current);
    }
    toStringCache = buffer.toString();
    return toStringCache;
  }
}

/**
 * The concatenation of two [DartString]s.
 */
class ConsDartString extends DartString {
  final DartString left;
  final DartString right;
  final int length;
  String toStringCache;
  ConsDartString(DartString left, DartString right)
      : this.left = left,
        this.right = right,
        length = left.length + right.length;

  Iterator<int> get iterator => new ConsDartStringIterator(this);

  String slowToString() {
    if (toStringCache != null) return toStringCache;
    toStringCache = left.slowToString() + right.slowToString();
    return toStringCache;
  }

  String get source => slowToString();
}

class ConsDartStringIterator implements Iterator<int> {
  HasNextIterator<int> currentIterator;
  DartString right;
  bool hasNextLookAhead;
  int _current = null;

  ConsDartStringIterator(ConsDartString cons)
      : currentIterator = new HasNextIterator<int>(cons.left.iterator),
        right = cons.right {
    hasNextLookAhead = currentIterator.hasNext;
    if (!hasNextLookAhead) {
      nextPart();
    }
  }

  int get current => _current;

  bool moveNext() {
    if (!hasNextLookAhead) {
      _current = null;
      return false;
    }
    _current = currentIterator.next();
    hasNextLookAhead = currentIterator.hasNext;
    if (!hasNextLookAhead) {
      nextPart();
    }
    return true;
  }

  void nextPart() {
    if (right != null) {
      currentIterator = new HasNextIterator<int>(right.iterator);
      right = null;
      hasNextLookAhead = currentIterator.hasNext;
    }
  }
}

/**
 *Iterator that returns the actual string contents of a string with escapes.
 */
class StringEscapeIterator implements Iterator<int> {
  final Iterator<int> source;
  int _current = null;

  StringEscapeIterator(String source) : this.source = source.codeUnits.iterator;

  int get current => _current;

  bool moveNext() {
    if (!source.moveNext()) {
      _current = null;
      return false;
    }
    int code = source.current;
    if (code != $BACKSLASH) {
      _current = code;
      return true;
    }
    source.moveNext();
    code = source.current;
    switch (code) {
      case $n:
        _current = $LF;
        break;
      case $r:
        _current = $CR;
        break;
      case $t:
        _current = $TAB;
        break;
      case $b:
        _current = $BS;
        break;
      case $f:
        _current = $FF;
        break;
      case $v:
        _current = $VTAB;
        break;
      case $x:
        source.moveNext();
        int value = hexDigitValue(source.current);
        source.moveNext();
        value = value * 16 + hexDigitValue(source.current);
        _current = value;
        break;
      case $u:
        int value = 0;
        source.moveNext();
        code = source.current;
        if (code == $OPEN_CURLY_BRACKET) {
          source.moveNext();
          while (source.current != $CLOSE_CURLY_BRACKET) {
            value = value * 16 + hexDigitValue(source.current);
            source.moveNext();
          }
          _current = value;
          break;
        }
        // Four digit hex value.
        value = hexDigitValue(code);
        for (int i = 0; i < 3; i++) {
          source.moveNext();
          value = value * 16 + hexDigitValue(source.current);
        }
        _current = value;
        break;
      default:
        _current = code;
    }
    return true;
  }
}
