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

/// Dart classes representing the souce spans and source files.
library source_maps.span;

import 'dart:math' show min, max;

import 'src/utils.dart';

/// A simple class that describe a segment of source text.
abstract class Span implements Comparable {
  /// The start location of this span.
  final Location start;

  /// The end location of this span, exclusive.
  final Location end;

  /// Url of the source (typically a file) containing this span.
  String get sourceUrl => start.sourceUrl;

  /// The length of this span, in characters.
  int get length => end.offset - start.offset;

  /// The source text for this span, if available.
  String get text;

  /// Whether [text] corresponds to an identifier symbol.
  final bool isIdentifier;

  Span(this.start, this.end, bool isIdentifier)
      : isIdentifier = isIdentifier != null ? isIdentifier : false {
    _checkRange();
  }

  /// Creates a new span that is the union of two existing spans [start] and
  /// [end]. Note that the resulting span might contain some positions that were
  /// not in either of the original spans if [start] and [end] are disjoint.
  Span.union(Span start, Span end)
      : start = start.start, end = end.end, isIdentifier = false {
    _checkRange();
  }

  void _checkRange() {
    if (start.offset < 0) throw new ArgumentError('start $start must be >= 0');
    if (end.offset < start.offset) {
      throw new ArgumentError('end $end must be >= start $start');
    }
  }

  /// Compares two spans. If the spans are not in the same source, this method
  /// generates an error.
  int compareTo(Span other) {
    int d = start.compareTo(other.start);
    return d == 0 ? end.compareTo(other.end) : d;
  }

  /// Gets the location in standard printed form `filename:line:column`, where
  /// line and column are adjusted by 1 to match the convention in editors.
  String get formatLocation => start.formatString;

  String getLocationMessage(String message,
      {bool useColors: false, String color}) {
    return '$formatLocation: $message';
  }

  bool operator ==(Span other) =>
    sourceUrl == other.sourceUrl && start == other.start && end == other.end;

  int get hashCode => sourceUrl.hashCode + start.offset + (31 * length);

  String toString() => '<$runtimeType: $start $end $formatLocation $text>';
}

/// A location in the source text
abstract class Location implements Comparable {
  /// Url of the source containing this span.
  String get sourceUrl;

  /// The offset of this location, 0-based.
  final int offset;

  /// The 0-based line in the source of this location.
  int get line;

  /// The 0-based column in the source of this location.
  int get column;

  Location(this.offset);

  /// Compares two locations. If the locations are not in the same source, this
  /// method generates an error.
  int compareTo(Location other) {
    if (sourceUrl != other.sourceUrl) {
      throw new ArgumentError('can only compare locations of the same source');
    }
    return offset - other.offset;
  }

  bool operator ==(Location other) =>
      sourceUrl == other.sourceUrl && offset == other.offset;

  int get hashCode => sourceUrl.hashCode + offset;

  String toString() => '(Location $offset)';
  String get formatString => '$sourceUrl:${line + 1}:${column + 1}';
}

/// Implementation of [Location] with fixed values given at allocation time.
class FixedLocation extends Location {
  final String sourceUrl;
  final int line;
  final int column;

  FixedLocation(int offset, this.sourceUrl, this.line, this.column)
      : super(offset);
}

/// Implementation of [Span] where all the values are given at allocation time.
class FixedSpan extends Span {
  /// The source text for this span, if available.
  final String text;

  /// Creates a span which starts and end in the same line.
  FixedSpan(String sourceUrl, int start, int line, int column,
            {String text: '', bool isIdentifier: false})
      : text = text, super(new FixedLocation(start, sourceUrl, line, column),
            new FixedLocation(start + text.length, sourceUrl, line,
                column + text.length),
            isIdentifier);
}

/// [Location] with values computed from an underling [SourceFile].
class FileLocation extends Location {
  /// The source file containing this location.
  final SourceFile file;

  String get sourceUrl => file.url;
  int get line => file.getLine(offset);
  int get column => file.getColumn(line, offset);

  FileLocation(this.file, int offset): super(offset);
}

/// [Span] where values are computed from an underling [SourceFile].
class FileSpan extends Span {
  /// The source file containing this span.
  final SourceFile file;

  /// The source text for this span, if available.
  String get text => file.getText(start.offset, end.offset);

  factory FileSpan(SourceFile file, int start,
      [int end, bool isIdentifier = false]) {
    var startLoc = new FileLocation(file, start);
    var endLoc = end == null ? startLoc : new FileLocation(file, end);
    return new FileSpan.locations(startLoc, endLoc, isIdentifier);
  }

  FileSpan.locations(FileLocation start, FileLocation end,
      bool isIdentifier)
      : file = start.file, super(start, end, isIdentifier);

  /// Creates a new span that is the union of two existing spans [start] and
  /// [end]. Note that the resulting span might contain some positions that were
  /// not in either of the original spans if [start] and [end] are disjoint.
  FileSpan.union(FileSpan start, FileSpan end)
      : file = start.file, super.union(start, end) {
    if (start.file != end.file) {
      throw new ArgumentError('start and end must be from the same file');
    }
  }

  String getLocationMessage(String message,
      {bool useColors: false, String color}) {
    return file.getLocationMessage(message, start.offset, end.offset,
        useColors: useColors, color: color);
  }
}

// Constants to determine end-of-lines.
const int _LF = 10;
const int _CR = 13;

// Color constants used for generating messages.
const String _RED_COLOR = '\u001b[31m';
const String _NO_COLOR = '\u001b[0m';

/// Stores information about a source file, to permit computation of the line
/// and column. Also contains a nice default error message highlighting the code
/// location.
class SourceFile {
  /// Url where the source file is located.
  final String url;
  final List<int> _lineStarts;
  final List<int> _decodedChars;

  SourceFile(this.url, this._lineStarts, this._decodedChars);

  SourceFile.text(this.url, String text)
      : _lineStarts = <int>[0],
        _decodedChars = text.runes.toList() {
    for (int i = 0; i < _decodedChars.length; i++) {
      var c = _decodedChars[i];
      if (c == _CR) {
        // Return not followed by newline is treated as a newline
        int j = i + 1;
        if (j >= _decodedChars.length || _decodedChars[j] != _LF) {
          c = _LF;
        }
      }
      if (c == _LF) _lineStarts.add(i + 1);
    }
  }

  /// Returns a span in this [SourceFile] with the given offsets.
  Span span(int start, [int end, bool isIdentifier = false]) =>
      new FileSpan(this, start, end, isIdentifier);

  /// Returns a location in this [SourceFile] with the given offset.
  Location location(int offset) => new FileLocation(this, offset);

  /// Gets the 0-based line corresponding to an offset.
  int getLine(int offset) => binarySearch(_lineStarts, (o) => o > offset) - 1;

  /// Gets the 0-based column corresponding to an offset.
  int getColumn(int line, int offset) {
    if (line < 0 || line >= _lineStarts.length) return 0;
    return offset - _lineStarts[line];
  }

  /// Get the offset for a given line and column
  int getOffset(int line, int column) {
    if (line < 0) return getOffset(0, 0);
    if (line < _lineStarts.length) {
      return _lineStarts[line] + column;
    } else {
      return _decodedChars.length;
    }
  }

  /// Gets the text at the given offsets.
  String getText(int start, [int end]) =>
      new String.fromCharCodes(_decodedChars.sublist(max(start, 0), end));

  /// Create a pretty string representation from a span.
  String getLocationMessage(String message, int start, int end,
      {bool useColors: false, String color}) {
    // TODO(jmesserly): it would be more useful to pass in an object that
    // controls how the errors are printed. This method is a bit too smart.
    var line = getLine(start);
    var column = getColumn(line, start);

    var src = url == null ? '' : url;
    var msg = '$src:${line + 1}:${column + 1}: $message';

    if (_decodedChars == null) {
      // We don't have any text to include, so exit.
      return msg;
    }

    var buf = new StringBuffer(msg);
    buf.write('\n');

    // +1 for 0-indexing, +1 again to avoid the last line
    var textLine = getText(getOffset(line, 0), getOffset(line + 1, 0));

    column = min(column, textLine.length - 1);
    int toColumn = min(column + end - start, textLine.length);
    if (useColors) {
      if (color == null) {
        color = _RED_COLOR;
      }
      buf.write(textLine.substring(0, column));
      buf.write(color);
      buf.write(textLine.substring(column, toColumn));
      buf.write(_NO_COLOR);
      buf.write(textLine.substring(toColumn));
    } else {
      buf.write(textLine);
      if (textLine != '' && !textLine.endsWith('\n')) buf.write('\n');
    }

    int i = 0;
    for (; i < column; i++) {
      buf.write(' ');
    }

    if (useColors) buf.write(color);
    for (; i < toColumn; i++) {
      buf.write('^');
    }
    if (useColors) buf.write(_NO_COLOR);
    return buf.toString();
  }
}

/// A convenience type to treat a code segment as if it were a separate
/// [SourceFile]. A [SourceFileSegment] shifts all locations by an offset, which
/// allows you to set source-map locations based on the locations relative to
/// the start of the segment, but that get translated to absolute locations in
/// the original source file.
class SourceFileSegment extends SourceFile {
  final int _baseOffset;
  final int _baseLine;
  final int _baseColumn;
  final int _maxOffset;

  SourceFileSegment(String url, String textSegment, Location startOffset)
      : _baseOffset = startOffset.offset,
        _baseLine = startOffset.line,
        _baseColumn = startOffset.column,
        _maxOffset = startOffset.offset + textSegment.length,
        super.text(url, textSegment);

  /// Craete a span, where [start] is relative to this segment's base offset.
  /// The returned span stores the real offset on the file, so that error
  /// messages are reported at the real location.
  Span span(int start, [int end, bool isIdentifier = false]) =>
      super.span(start + _baseOffset,
          end == null ? null : end + _baseOffset, isIdentifier);

  /// Create a location, where [offset] relative to this segment's base offset.
  /// The returned span stores the real offset on the file, so that error
  /// messages are reported at the real location.
  Location location(int offset) => super.location(offset + _baseOffset);

  /// Return the line on the underlying file associated with the [offset] of the
  /// underlying file. This method operates on the real offsets from the
  /// original file, so that error messages can be reported accurately. When the
  /// requested offset is past the length of the segment, this returns the line
  /// number after the end of the segment (total lines + 1).
  int getLine(int offset) {
    var res = super.getLine(max(offset - _baseOffset, 0)) + _baseLine;
    return (offset > _maxOffset) ? res + 1 : res;
  }

  /// Return the column on the underlying file associated with [line] and
  /// [offset], where [line] is absolute from the beginning of the underlying
  /// file. This method operates on the real offsets from the original file, so
  /// that error messages can be reported accurately.
  int getColumn(int line, int offset) {
    var col = super.getColumn(line - _baseLine, max(offset - _baseOffset, 0));
    return line == _baseLine ? col + _baseColumn : col;
  }

  /// Return the offset associated with a line and column. This method operates
  /// on the real offsets from the original file, so that error messages can be
  /// reported accurately.
  int getOffset(int line, int column) =>
    super.getOffset(line - _baseLine,
        line == _baseLine ? column - _baseColumn : column) + _baseOffset;

  /// Retrieve the text associated with the specified range. This method
  /// operates on the real offsets from the original file, so that error
  /// messages can be reported accurately.
  String getText(int start, [int end]) =>
    super.getText(start - _baseOffset, end == null ? null : end - _baseOffset);
}
