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

/** The one true [World]. */
World world;

typedef void MessageHandler(String prefix, String message, SourceSpan span);
typedef void PrintHandler(String message);

/**
 * Should be called exactly once to setup singleton world.
 * Can use world.reset() to reinitialize.
 */
void initializeWorld(var files) {
  assert(world == null);
  world = new World(files);
  world.init();
}

/** Can be thrown on any compiler error and includes source location. */
class CompilerException implements Exception {
  final String _message;
  final SourceSpan _location;

  CompilerException(this._message, this._location);

  String toString() {
    if (_location != null) {
      return 'CompilerException: ${_location.toMessageString(_message)}';
    } else {
      return 'CompilerException: $_message';
    }
  }
}

/** Represents a Dart template "world". */
class World {
  String template;

  var files;

  int errors = 0, warnings = 0;
  bool seenFatal = false;
  MessageHandler messageHandler;
  PrintHandler printHandler;

  World(this.files);

  void reset() {
    errors = warnings = 0;
    seenFatal = false;
    init();
  }

  init() {
  }


  // ********************** Message support ***********************

  void _message(String color, String prefix, String message,
      SourceSpan span, SourceSpan span1, SourceSpan span2, bool throwing) {
    if (messageHandler != null) {
      // TODO(jimhug): Multiple spans cleaner...
      messageHandler(prefix, message, span);
      if (span1 != null) {
        messageHandler(prefix, message, span1);
      }
      if (span2 != null) {
        messageHandler(prefix, message, span2);
      }
    } else {
      final messageWithPrefix = options.useColors
          ? (color + prefix + _NO_COLOR + message) : (prefix + message);

      var text = messageWithPrefix;
      if (span != null) {
        text = span.toMessageString(messageWithPrefix);
      }

      String span1Text = span1 != null ?
          span1.toMessageString(messageWithPrefix) : "";
      String span2Text = span2 != null ?
          span2.toMessageString(messageWithPrefix) : "";

      if (printHandler == null) {
        print(text);
        if (span1 != null) {
          print(span1Text);
        }
        if (span2 != null) {
          print(span2Text);
        }
      } else {
        printHandler("${text}\r${span1Text}\r${span2Text}");
      }
    }

    if (throwing) {
      throw new CompilerException(prefix + message, span);
    }
  }

  /** [message] is considered a static compile-time error by the Dart lang. */
  void error(String message,
      [SourceSpan span, SourceSpan span1, SourceSpan span2]) {
    errors++;
    _message(_RED_COLOR, 'error: ', message,
        span, span1, span2, options.throwOnErrors);
  }

  /** [message] is considered a type warning by the Dart lang. */
  void warning(String message,
      [SourceSpan span, SourceSpan span1, SourceSpan span2]) {
    if (options.warningsAsErrors) {
      error(message, span, span1, span2);
      return;
    }
    warnings++;
    if (options.showWarnings) {
      _message(_MAGENTA_COLOR, 'warning: ', message,
          span, span1, span2, options.throwOnWarnings);
    }
  }

  /** [message] at [location] is so bad we can't generate runnable code. */
  void fatal(String message,
      [SourceSpan span, SourceSpan span1, SourceSpan span2]) {
    errors++;
    seenFatal = true;
    _message(_RED_COLOR, 'fatal: ', message,
        span, span1, span2, options.throwOnFatal || options.throwOnErrors);
  }

  /** [message] at [location] is about a bug in the compiler. */
  void internalError(String message,
      {SourceSpan span, SourceSpan span1, SourceSpan span2}) {
    _message(_NO_COLOR,
        'We are sorry, but...', message, span, span1, span2, true);
  }

  /**
   * [message] at [location] will tell the user about what the compiler
   * is doing.
   */
  void info(String message,
      [SourceSpan span, SourceSpan span1, SourceSpan span2]) {
    if (options.showInfo) {
      _message(_GREEN_COLOR, 'info: ', message, span, span1, span2, false);
    }
  }

  bool get hasErrors => errors > 0;

  withTiming(String name, f()) {
    final sw = new Stopwatch();
    sw.start();
    var result = f();
    sw.stop();
    info('$name in ${sw.elapsedMilliseconds}msec');
    return result;
  }
}

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