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

library csslib.src.messages;

import 'package:logging/logging.dart' show Level;
import 'package:source_maps/span.dart' show Span;

import 'package:csslib/parser.dart';

import 'options.dart';

// TODO(terry): Remove the global messages, use some object that tracks
//              compilation state.

/** The global [Messages] for tracking info/warnings/messages. */
Messages messages;

// Color constants used for generating messages.
final String GREEN_COLOR = '\u001b[32m';
final String RED_COLOR = '\u001b[31m';
final String MAGENTA_COLOR = '\u001b[35m';
final String NO_COLOR = '\u001b[0m';

/** Map between error levels and their display color. */
final Map<Level, String> _ERROR_COLORS = (() {
  var colorsMap = new Map<Level, String>();
  colorsMap[Level.SEVERE] = RED_COLOR;
  colorsMap[Level.WARNING] = MAGENTA_COLOR;
  colorsMap[Level.INFO] = GREEN_COLOR;
  return colorsMap;
})();

/** Map between error levels and their friendly name. */
final Map<Level, String> _ERROR_LABEL = (() {
  var labels = new Map<Level, String>();
  labels[Level.SEVERE] = 'error';
  labels[Level.WARNING] = 'warning';
  labels[Level.INFO] = 'info';
  return labels;
})();

/** A single message from the compiler. */
class Message {
  final Level level;
  final String message;
  final Span span;
  final bool useColors;

  Message(this.level, this.message, {Span span, bool useColors: false})
      : this.span = span, this.useColors = useColors;

  String toString() {
    var output = new StringBuffer();
    bool colors = useColors && _ERROR_COLORS.containsKey(level);
    var levelColor =  _ERROR_COLORS[level];
    if (colors) output.write(levelColor);
    output..write(_ERROR_LABEL[level])..write(' ');
    if (colors) output.write(NO_COLOR);

    if (span == null) {
      output.write(message);
    } else {
      output.write(span.getLocationMessage(message, useColors: colors,
          color: levelColor));
    }

    return output.toString();
  }
}

typedef void PrintHandler(Object obj);

/**
 * This class tracks and prints information, warnings, and errors emitted by the
 * compiler.
 */
class Messages {
  /** Called on every error. Set to blank function to supress printing. */
  final PrintHandler printHandler;

  final PreprocessorOptions options;

  final List<Message> messages = <Message>[];

  Messages({PreprocessorOptions options, this.printHandler: print})
      : options = options != null ? options : new PreprocessorOptions();

  /** Report a compile-time CSS error. */
  void error(String message, Span span) {
    var msg = new Message(Level.SEVERE, message, span: span,
        useColors: options.useColors);

    messages.add(msg);

    printHandler(msg);
  }

  /** Report a compile-time CSS warning. */
  void warning(String message, Span span) {
    if (options.warningsAsErrors) {
      error(message, span);
    } else {
      var msg = new Message(Level.WARNING, message, span: span,
          useColors: options.useColors);

      messages.add(msg);
    }
  }

  /** Report and informational message about what the compiler is doing. */
  void info(String message, Span span) {
    var msg = new Message(Level.INFO, message, span: span,
        useColors: options.useColors);

    messages.add(msg);

    if (options.verbose) printHandler(msg);
  }

  /** Merge [newMessages] to this message lsit. */
  void mergeMessages(Messages newMessages) {
    messages.addAll(newMessages.messages);
    newMessages.messages.where((message) =>
        message.level.value == Level.SEVERE || options.verbose)
        .forEach((message) { printHandler(message); });
  }
}
