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

import 'location.dart';
import 'location_mixin.dart';
import 'span.dart';
import 'span_mixin.dart';
import 'span_with_context.dart';

// Constants to determine end-of-lines.
const int _lf = 10;
const int _cr = 13;

/// A class representing a source file.
///
/// This doesn't necessarily have to correspond to a file on disk, just a chunk
/// of text usually with a URL associated with it.
class SourceFile {
  /// The URL where the source file is located.
  ///
  /// This may be null, indicating that the URL is unknown or unavailable.
  final Uri url;

  /// An array of offsets for each line beginning in the file.
  ///
  /// Each offset refers to the first character *after* the newline. If the
  /// source file has a trailing newline, the final offset won't actually be in
  /// the file.
  final _lineStarts = <int>[0];

  /// The code points of the characters in the file.
  final Uint32List _decodedChars;

  /// The length of the file in characters.
  int get length => _decodedChars.length;

  /// The number of lines in the file.
  int get lines => _lineStarts.length;

  /// The line that the offset fell on the last time [getLine] was called.
  ///
  /// In many cases, sequential calls to getLine() are for nearby, usually
  /// increasing offsets. In that case, we can find the line for an offset
  /// quickly by first checking to see if the offset is on the same line as the
  /// previous result.
  int _cachedLine;

  /// This constructor is deprecated.
  ///
  /// Use [new SourceFile.fromString] instead.
  @Deprecated('Will be removed in 2.0.0')
  SourceFile(String text, {url}) : this.decoded(text.runes, url: url);

  /// Creates a new source file from [text].
  ///
  /// [url] may be either a [String], a [Uri], or `null`.
  SourceFile.fromString(String text, {url})
      : this.decoded(text.codeUnits, url: url);

  /// Creates a new source file from a list of decoded code units.
  ///
  /// [url] may be either a [String], a [Uri], or `null`.
  ///
  /// Currently, if [decodedChars] contains characters larger than `0xFFFF`,
  /// they'll be treated as single characters rather than being split into
  /// surrogate pairs. **This behavior is deprecated**. For
  /// forwards-compatibility, callers should only pass in characters less than
  /// or equal to `0xFFFF`.
  SourceFile.decoded(Iterable<int> decodedChars, {url})
      : url = url is String ? Uri.parse(url) : url as Uri,
        _decodedChars = Uint32List.fromList(decodedChars.toList()) {
    for (var i = 0; i < _decodedChars.length; i++) {
      var c = _decodedChars[i];
      if (c == _cr) {
        // Return not followed by newline is treated as a newline
        final j = i + 1;
        if (j >= _decodedChars.length || _decodedChars[j] != _lf) c = _lf;
      }
      if (c == _lf) _lineStarts.add(i + 1);
    }
  }

  /// Returns a span from [start] to [end] (exclusive).
  ///
  /// If [end] isn't passed, it defaults to the end of the file.
  FileSpan span(int start, [int end]) {
    end ??= length;
    return _FileSpan(this, start, end);
  }

  /// Returns a location at [offset].
  FileLocation location(int offset) => FileLocation._(this, offset);

  /// Gets the 0-based line corresponding to [offset].
  int getLine(int offset) {
    if (offset < 0) {
      throw RangeError('Offset may not be negative, was $offset.');
    } else if (offset > length) {
      throw RangeError('Offset $offset must not be greater than the number '
          'of characters in the file, $length.');
    }

    if (offset < _lineStarts.first) return -1;
    if (offset >= _lineStarts.last) return _lineStarts.length - 1;

    if (_isNearCachedLine(offset)) return _cachedLine;

    _cachedLine = _binarySearch(offset) - 1;
    return _cachedLine;
  }

  /// Returns `true` if [offset] is near [_cachedLine].
  ///
  /// Checks on [_cachedLine] and the next line. If it's on the next line, it
  /// updates [_cachedLine] to point to that.
  bool _isNearCachedLine(int offset) {
    if (_cachedLine == null) return false;

    // See if it's before the cached line.
    if (offset < _lineStarts[_cachedLine]) return false;

    // See if it's on the cached line.
    if (_cachedLine >= _lineStarts.length - 1 ||
        offset < _lineStarts[_cachedLine + 1]) {
      return true;
    }

    // See if it's on the next line.
    if (_cachedLine >= _lineStarts.length - 2 ||
        offset < _lineStarts[_cachedLine + 2]) {
      _cachedLine++;
      return true;
    }

    return false;
  }

  /// Binary search through [_lineStarts] to find the line containing [offset].
  ///
  /// Returns the index of the line in [_lineStarts].
  int _binarySearch(int offset) {
    var min = 0;
    var max = _lineStarts.length - 1;
    while (min < max) {
      final half = min + ((max - min) ~/ 2);
      if (_lineStarts[half] > offset) {
        max = half;
      } else {
        min = half + 1;
      }
    }

    return max;
  }

  /// Gets the 0-based column corresponding to [offset].
  ///
  /// If [line] is passed, it's assumed to be the line containing [offset] and
  /// is used to more efficiently compute the column.
  int getColumn(int offset, {int line}) {
    if (offset < 0) {
      throw RangeError('Offset may not be negative, was $offset.');
    } else if (offset > length) {
      throw RangeError('Offset $offset must be not be greater than the '
          'number of characters in the file, $length.');
    }

    if (line == null) {
      line = getLine(offset);
    } else if (line < 0) {
      throw RangeError('Line may not be negative, was $line.');
    } else if (line >= lines) {
      throw RangeError('Line $line must be less than the number of '
          'lines in the file, $lines.');
    }

    final lineStart = _lineStarts[line];
    if (lineStart > offset) {
      throw RangeError('Line $line comes after offset $offset.');
    }

    return offset - lineStart;
  }

  /// Gets the offset for a [line] and [column].
  ///
  /// [column] defaults to 0.
  int getOffset(int line, [int column]) {
    column ??= 0;

    if (line < 0) {
      throw RangeError('Line may not be negative, was $line.');
    } else if (line >= lines) {
      throw RangeError('Line $line must be less than the number of '
          'lines in the file, $lines.');
    } else if (column < 0) {
      throw RangeError('Column may not be negative, was $column.');
    }

    final result = _lineStarts[line] + column;
    if (result > length ||
        (line + 1 < lines && result >= _lineStarts[line + 1])) {
      throw RangeError("Line $line doesn't have $column columns.");
    }

    return result;
  }

  /// Returns the text of the file from [start] to [end] (exclusive).
  ///
  /// If [end] isn't passed, it defaults to the end of the file.
  String getText(int start, [int end]) =>
      String.fromCharCodes(_decodedChars.sublist(start, end));
}

/// A [SourceLocation] within a [SourceFile].
///
/// Unlike the base [SourceLocation], [FileLocation] lazily computes its line
/// and column values based on its offset and the contents of [file].
///
/// A [FileLocation] can be created using [SourceFile.location].
class FileLocation extends SourceLocationMixin implements SourceLocation {
  /// The [file] that `this` belongs to.
  final SourceFile file;

  @override
  final int offset;

  @override
  Uri get sourceUrl => file.url;

  @override
  int get line => file.getLine(offset);

  @override
  int get column => file.getColumn(offset);

  FileLocation._(this.file, this.offset) {
    if (offset < 0) {
      throw RangeError('Offset may not be negative, was $offset.');
    } else if (offset > file.length) {
      throw RangeError('Offset $offset must not be greater than the number '
          'of characters in the file, ${file.length}.');
    }
  }

  @override
  FileSpan pointSpan() => _FileSpan(file, offset, offset);
}

/// A [SourceSpan] within a [SourceFile].
///
/// Unlike the base [SourceSpan], [FileSpan] lazily computes its line and column
/// values based on its offset and the contents of [file]. [SourceSpan.message]
/// is also able to provide more context then [SourceSpan.message], and
/// [SourceSpan.union] will return a [FileSpan] if possible.
///
/// A [FileSpan] can be created using [SourceFile.span].
abstract class FileSpan implements SourceSpanWithContext {
  /// The [file] that `this` belongs to.
  SourceFile get file;

  @override
  FileLocation get start;

  @override
  FileLocation get end;

  /// Returns a new span that covers both `this` and [other].
  ///
  /// Unlike [union], [other] may be disjoint from `this`. If it is, the text
  /// between the two will be covered by the returned span.
  FileSpan expand(FileSpan other);
}

/// The implementation of [FileSpan].
///
/// This is split into a separate class so that `is _FileSpan` checks can be run
/// to make certain operations more efficient. If we used `is FileSpan`, that
/// would break if external classes implemented the interface.
class _FileSpan extends SourceSpanMixin implements FileSpan {
  @override
  final SourceFile file;

  /// The offset of the beginning of the span.
  ///
  /// [start] is lazily generated from this to avoid allocating unnecessary
  /// objects.
  final int _start;

  /// The offset of the end of the span.
  ///
  /// [end] is lazily generated from this to avoid allocating unnecessary
  /// objects.
  final int _end;

  @override
  Uri get sourceUrl => file.url;

  @override
  int get length => _end - _start;

  @override
  FileLocation get start => FileLocation._(file, _start);

  @override
  FileLocation get end => FileLocation._(file, _end);

  @override
  String get text => file.getText(_start, _end);

  @override
  String get context {
    final endLine = file.getLine(_end);
    final endColumn = file.getColumn(_end);

    int endOffset;
    if (endColumn == 0 && endLine != 0) {
      // If [end] is at the very beginning of the line, the span covers the
      // previous newline, so we only want to include the previous line in the
      // context...

      if (length == 0) {
        // ...unless this is a point span, in which case we want to include the
        // next line (or the empty string if this is the end of the file).
        return endLine == file.lines - 1
            ? ''
            : file.getText(
                file.getOffset(endLine), file.getOffset(endLine + 1));
      }

      endOffset = _end;
    } else if (endLine == file.lines - 1) {
      // If the span covers the last line of the file, the context should go all
      // the way to the end of the file.
      endOffset = file.length;
    } else {
      // Otherwise, the context should cover the full line on which [end]
      // appears.
      endOffset = file.getOffset(endLine + 1);
    }

    return file.getText(file.getOffset(file.getLine(_start)), endOffset);
  }

  _FileSpan(this.file, this._start, this._end) {
    if (_end < _start) {
      throw ArgumentError('End $_end must come after start $_start.');
    } else if (_end > file.length) {
      throw RangeError('End $_end must not be greater than the number '
          'of characters in the file, ${file.length}.');
    } else if (_start < 0) {
      throw RangeError('Start may not be negative, was $_start.');
    }
  }

  @override
  int compareTo(SourceSpan other) {
    if (other is! _FileSpan) return super.compareTo(other);

    final otherFile = other as _FileSpan;
    final result = _start.compareTo(otherFile._start);
    return result == 0 ? _end.compareTo(otherFile._end) : result;
  }

  @override
  SourceSpan union(SourceSpan other) {
    if (other is! FileSpan) return super.union(other);

    final span = expand(other as _FileSpan);

    if (other is _FileSpan) {
      if (_start > other._end || other._start > _end) {
        throw ArgumentError('Spans $this and $other are disjoint.');
      }
    } else {
      if (_start > other.end.offset || other.start.offset > _end) {
        throw ArgumentError('Spans $this and $other are disjoint.');
      }
    }

    return span;
  }

  @override
  bool operator ==(other) {
    if (other is! FileSpan) return super == other;
    if (other is! _FileSpan) {
      return super == other && sourceUrl == other.sourceUrl;
    }

    return _start == other._start &&
        _end == other._end &&
        sourceUrl == other.sourceUrl;
  }

  // Eliminates dart2js warning about overriding `==`, but not `hashCode`
  @override
  int get hashCode => super.hashCode;

  /// Returns a new span that covers both `this` and [other].
  ///
  /// Unlike [union], [other] may be disjoint from `this`. If it is, the text
  /// between the two will be covered by the returned span.
  @override
  FileSpan expand(FileSpan other) {
    if (sourceUrl != other.sourceUrl) {
      throw ArgumentError('Source URLs \"$sourceUrl\" and '
          " \"${other.sourceUrl}\" don't match.");
    }

    if (other is _FileSpan) {
      final start = math.min(_start, other._start);
      final end = math.max(_end, other._end);
      return _FileSpan(file, start, end);
    } else {
      final start = math.min(_start, other.start.offset);
      final end = math.max(_end, other.end.offset);
      return _FileSpan(file, start, end);
    }
  }

  /// See `SourceSpanExtension.subspan`.
  FileSpan subspan(int start, [int end]) {
    RangeError.checkValidRange(start, end, length);
    if (start == 0 && (end == null || end == length)) return this;
    return file.span(_start + start, end == null ? _end : _start + end);
  }
}

// TODO(#52): Move these to instance methods in the next breaking release.
/// Extension methods on the [FileSpan] API.
extension FileSpanExtension on FileSpan {
  /// See `SourceSpanExtension.subspan`.
  FileSpan subspan(int start, [int end]) {
    RangeError.checkValidRange(start, end, length);
    if (start == 0 && (end == null || end == length)) return this;

    final startOffset = this.start.offset;
    return file.span(
        startOffset + start, end == null ? this.end.offset : startOffset + end);
  }
}
