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

package com.google.dart.compiler;

import com.google.common.io.Closeables;
import com.google.dart.compiler.CompilerConfiguration.ErrorFormat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintStream;
import java.io.Reader;

/**
 * An error formatter that scans the source file and prints the error line and
 * some context around it. This formatter has two modes: with or without color.
 * When using colors, it prints the error message in red, and it highlights the
 * portion of the line containing the error in red. Without colors, it prints an
 * extra line underlying the portion of the line containing the error.
 */
public class PrettyErrorFormatter extends DefaultErrorFormatter {
  public static final String ERROR_BOLD_COLOR = "\033[31;1m";
  public static final String ERROR_COLOR = "\033[31m";

  // Mix ANSI with xterm colors, giving ANSI priority.  The terminal should ignore xterm codes
  // if it doesn't support them.
  public static final String WARNING_BOLD_COLOR = "\033[33;1m\033[38;5;202m";
  public static final String WARNING_COLOR = "\033[33m\033[38;5;208m";

  public static final String NO_COLOR = "\033[0m";

  private final boolean useColor;

  public PrettyErrorFormatter(PrintStream outputStream,
      boolean useColor,
      ErrorFormat errorFormat) {
    super(outputStream, errorFormat);
    this.useColor = useColor;
  }

  @Override
  public void format(DartCompilationError event) {
    Source sourceFile = event.getSource();

    // if this is an unknown source type, default to the basic error formatter
    if (!(sourceFile instanceof DartSource) && !(sourceFile instanceof LibrarySource)) {
      super.format(event);
      return;
    }

    BufferedReader reader = null;
    try {
      Reader sourceReader = sourceFile.getSourceReader();
      if (sourceReader != null) {
        reader = new BufferedReader(sourceReader);
      }

      // get the error line and the line above it (note: line starts at 1)
      int line = event.getLineNumber();
      String lineBefore = null;
      String lineText = null;

      if (reader != null) {
        lineBefore = getLineAt(reader, line - 1);
        lineText = getLineAt(reader, 1);
      }

      // if there is no line to highlight, default to the basic error formatter
      if (lineText == null) {
        super.format(event);
        return;
      }

      // get column/length and ensure they are within the line limits.
      int col = event.getColumnNumber() - 1;
      int length = event.getLength();
      col = between(col, 0, lineText.length());
      length = between(length, 0, lineText.length() - col);
      length = length == 0 ? lineText.length() - col : length;

      // print the error message
      StringBuilder buf = new StringBuilder();
      if (useColor) {
        buf.append(event.getErrorCode().getErrorSeverity() == ErrorSeverity.WARNING
            ? WARNING_BOLD_COLOR : ERROR_BOLD_COLOR);
      }
      if (errorFormat == ErrorFormat.MACHINE) {
        buf.append(String.format(
            "%s|%s|%s|%s|%d|%d|%d|%s",
            escapePipe(event.getErrorCode().getErrorSeverity().toString()),
            escapePipe(event.getErrorCode().getSubSystem().toString()),
            escapePipe(event.getErrorCode().toString()),
            escapePipe(getSourceName(sourceFile)),
            event.getLineNumber(),
            1 + col,
            length,
            escapePipe(event.getMessage())));
      } else {
        String sourceName = sourceFile.getUri().toString();
        String includeFrom = getImportString(sourceFile);
        buf.append(String.format(
            "%s:%d: %s%s",
            sourceName,
            event.getLineNumber(),
            event.getMessage(),
            includeFrom));
      }
      if (useColor) {
        buf.append(NO_COLOR);
      }
      buf.append("\n");
      // show the previous line for context
      if (lineBefore != null) {
        buf.append(String.format("%6d: %s\n", line - 1, lineBefore));
      }

      if (useColor) {
        // highlight error in red
        buf.append(String.format("%6d: %s%s%s%s%s\n",
              line,
              lineText.substring(0, col),
              event.getErrorCode().getErrorSeverity() == ErrorSeverity.WARNING
              ? WARNING_COLOR : ERROR_COLOR,
              lineText.substring(col, col + length),
              NO_COLOR,
              lineText.substring(col + length)));
      } else {
        // print the error line without formatting
        buf.append(String.format("%6d: %s\n", line, lineText));

        // underline error portion
        buf.append("        ");
        for (int i = 0; i < col; ++i) {
          buf.append(' ');
        }
        buf.append('~');
        if (length > 1) {
          for (int i = 0; i < length - 2; ++i) {
            buf.append('~');
          }
          buf.append('~');
        }
        buf.append('\n');
      }

      outputStream.print(buf.toString());
    } catch (IOException ex) {
      super.format(event);
    } finally {
      if (reader != null) {
        Closeables.closeQuietly(reader);
      }
    }
  }
  
  private static String getSourceName(Source source) {
    if (source instanceof UrlDartSource) {
      return source.getUri().toString();
    }
    return source.getName();
  }

  private String escapePipe(String input) {
    StringBuilder result = new StringBuilder();
    for (char c : input.toCharArray()) {
      if (c == '\\' || c == '|') {
        result.append('\\');
      }
      result.append(c);
    }
    return result.toString();
  }

  private String getLineAt(BufferedReader reader, int line) throws IOException {
    if (line <= 0) {
      return null;
    }
    String currentLine = null;
    // TODO(sigmund): do something more efficient - we currently do a linear
    // scan of the file every time an error is reported. This will not scale
    // when many errors are reported on the same file.
    while ((currentLine = reader.readLine()) != null && line-- > 1){}
    return currentLine;
  }

  /**
   * Returns the closest value in {@code [start,end]} to the given value. If
   * the given range is entirely empty, then {@code start} is returned.
   */
  private static int between(int val, int start, int end) {
    return Math.max(start, Math.min(val, end));
  }
}
