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

// TODO(jimhug): This should be an interface to work better with tools.
/**
 * Represents a file of source code.
 */
class SourceFile implements Comparable<SourceFile> {
  // TODO(terry): This filename for in memory buffer.  May need to rework if
  //              filename is used for more than informational.
  static String IN_MEMORY_FILE = '<buffer>';

  /** The name of the file. */
  final String filename;

  /** The text content of the file. */
  String _text;

  /**
   * The order of the source file in a given library. This is used while we're
   * writing code for a library. A single source file can be used
   */
  // TODO(jmesserly): I don't like having properties that are only valid
  // sometimes. An alternative would be to store it in a Map that's used by
  // WorldGenerator while it's emitting code. This seems simpler.
  int orderInLibrary;

  List<int> _lineStarts;

  SourceFile(this.filename, this._text);

  String get text => _text;

  set text(String newText) {
    if (newText != _text) {
      _text = newText;
      _lineStarts = null;
      orderInLibrary = null;
    }
  }

  List<int> get lineStarts {
    if (_lineStarts == null) {
      var starts = [0];
      var index = 0;
      while (index < text.length) {
        index = text.indexOf('\n', index) + 1;
        if (index <= 0) break;
        starts.add(index);
      }
      starts.add(text.length + 1);
      _lineStarts = starts;
    }
    return _lineStarts;
  }

  int getLine(int position) {
    // TODO(jimhug): Implement as binary search.
    var starts = lineStarts;
    for (int i=0; i < starts.length; i++) {
      if (starts[i] > position) return i-1;
    }
    world.internalError('bad position');
  }

  int getColumn(int line, int position) {
    return position - lineStarts[line];
  }

  /**
   * Create a pretty string representation from a character position
   * in the file.
   */
  String getLocationMessage(String message, int start,
      [int end, bool includeText=false]) {
    var line = getLine(start);
    var column = getColumn(line, start);

    var buf = new StringBuffer(
        '${filename}:${line + 1}:${column + 1}: $message');
    if (includeText) {
      buf.write('\n');
      var textLine;
      // +1 for 0-indexing, +1 again to avoid the last line of the file
      if ((line + 2) < _lineStarts.length) {
        textLine = text.substring(_lineStarts[line], _lineStarts[line+1]);
      } else {
        textLine = text.substring(_lineStarts[line]) + '\n';
      }

      int toColumn = Math.min(column + (end-start), textLine.length);
      if (options.useColors) {
        buf.write(textLine.substring(0, column));
        buf.write(_RED_COLOR);
        buf.write(textLine.substring(column, toColumn));
        buf.write(_NO_COLOR);
        buf.write(textLine.substring(toColumn));
      } else {
        buf.write(textLine);
      }

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

      if (options.useColors) buf.write(_RED_COLOR);
      for (; i < toColumn; i++) {
        buf.write('^');
      }
      if (options.useColors) buf.write(_NO_COLOR);
    }

    return buf.toString();
  }

  /** Compares two source files. */
  int compareTo(SourceFile other) {
    if (orderInLibrary != null && other.orderInLibrary != null) {
      return orderInLibrary - other.orderInLibrary;
    } else {
      return filename.compareTo(other.filename);
    }
  }
}


/**
 * A range of characters in a [SourceFile].  Used to represent the source
 * positions of [Token]s and [Node]s for error reporting or other tooling
 * work.
 */
 // TODO(jmesserly): Rename to Span - but first write cool refactoring tool
class SourceSpan implements Comparable<SourceSpan> {
  /** The [SourceFile] that contains this span. */
  final SourceFile file;

  /** The character position of the start of this span. */
  final int start;

  /** The character position of the end of this span. */
  final int end;

  SourceSpan(this.file, this.start, this.end);

  /** Returns the source text corresponding to this [Span]. */
  String get text {
    return file.text.substring(start, end);
  }

  toMessageString(String message) {
    return file.getLocationMessage(message, start, end: end, includeText: true);
  }

  int get line {
    return file.getLine(start);
  }

  int get column {
    return file.getColumn(line, start);
  }

  int get endLine {
    return file.getLine(end);
  }

  int get endColumn {
    return file.getColumn(endLine, end);
  }

  String get locationText {
    var line = file.getLine(start);
    var column = file.getColumn(line, start);
    return '${file.filename}:${line + 1}:${column + 1}';
  }

  /** Compares two source spans by file and position. Handles nulls. */
  int compareTo(SourceSpan other) {
    if (file == other.file) {
      int d = start - other.start;
      return d == 0 ? (end - other.end) : d;
    }
    return file.compareTo(other.file);
  }
}
