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

library source_file_provider;

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:math' as math;

import '../compiler.dart' as api show Diagnostic, DiagnosticHandler;
import '../compiler_new.dart' as api show CompilerInput, CompilerDiagnostics;
import 'dart2js.dart' show AbortLeg;
import 'colors.dart' as colors;
import 'io/source_file.dart';
import 'filenames.dart';
import 'util/uri_extras.dart';
import 'dart:typed_data';
import '../compiler_new.dart';

List<int> readAll(String filename) {
  var file = (new File(filename)).openSync();
  var length = file.lengthSync();
  // +1 to have a 0 terminated list, see [Scanner].
  var buffer = new Uint8List(length + 1);
  file.readIntoSync(buffer, 0, length);
  file.closeSync();
  return buffer;
}

abstract class SourceFileProvider implements CompilerInput {
  bool isWindows = (Platform.operatingSystem == 'windows');
  Uri cwd = currentDirectory;
  Map<Uri, SourceFile> sourceFiles = <Uri, SourceFile>{};
  int dartCharactersRead = 0;

  Future<String> readStringFromUri(Uri resourceUri) {
    return readUtf8BytesFromUri(resourceUri).then(UTF8.decode);
  }

  Future<List<int>> readUtf8BytesFromUri(Uri resourceUri) {
    if (resourceUri.scheme == 'file') {
      return _readFromFile(resourceUri);
    } else if (resourceUri.scheme == 'http' || resourceUri.scheme == 'https') {
      return _readFromHttp(resourceUri);
    } else {
      throw new ArgumentError("Unknown scheme in uri '$resourceUri'");
    }
  }

  Future<List<int>> _readFromFile(Uri resourceUri) {
    assert(resourceUri.scheme == 'file');
    List<int> source;
    try {
      source = readAll(resourceUri.toFilePath());
    } on FileSystemException catch (ex) {
      OSError ose = ex.osError;
      String detail = (ose != null && ose.message != null)
          ? ' (${ose.message})'
          : '';
      return new Future.error(
          "Error reading '${relativize(cwd, resourceUri, isWindows)}'"
          "$detail");
    }
    dartCharactersRead += source.length;
    sourceFiles[resourceUri] =
        new CachingUtf8BytesSourceFile(
            resourceUri, relativizeUri(resourceUri), source);
    return new Future.value(source);
  }

  Future<List<int>> _readFromHttp(Uri resourceUri) {
    assert(resourceUri.scheme == 'http');
    HttpClient client = new HttpClient();
    return client.getUrl(resourceUri)
        .then((HttpClientRequest request) => request.close())
        .then((HttpClientResponse response) {
          if (response.statusCode != HttpStatus.OK) {
            String msg = 'Failure getting $resourceUri: '
                      '${response.statusCode} ${response.reasonPhrase}';
            throw msg;
          }
          return response.toList();
        })
        .then((List<List<int>> splitContent) {
           int totalLength = splitContent.fold(0, (int old, List list) {
             return old + list.length;
           });
           Uint8List result = new Uint8List(totalLength);
           int offset = 0;
           for (List<int> contentPart in splitContent) {
             result.setRange(
                 offset, offset + contentPart.length, contentPart);
             offset += contentPart.length;
           }
           dartCharactersRead += totalLength;
           sourceFiles[resourceUri] =
               new CachingUtf8BytesSourceFile(
                   resourceUri, resourceUri.toString(), result);
           return result;
         });
  }

  // TODO(johnniwinther): Remove this when no longer needed for the old compiler
  // API.
  Future/*<List<int> | String>*/ call(Uri resourceUri);

  relativizeUri(Uri uri) => relativize(cwd, uri, isWindows);

  SourceFile getSourceFile(Uri resourceUri) {
    return sourceFiles[resourceUri];
  }
}

class CompilerSourceFileProvider extends SourceFileProvider {
  // TODO(johnniwinther): Remove this when no longer needed for the old compiler
  // API.
  Future<List<int>> call(Uri resourceUri) => readFromUri(resourceUri);

  @override
  Future readFromUri(Uri uri) => readUtf8BytesFromUri(uri);
}

class FormattingDiagnosticHandler implements CompilerDiagnostics {
  final SourceFileProvider provider;
  bool showWarnings = true;
  bool showHints = true;
  bool verbose = false;
  bool isAborting = false;
  bool enableColors = false;
  bool throwOnError = false;
  int throwOnErrorCount = 0;
  api.Diagnostic lastKind = null;
  int fatalCount = 0;

  final int FATAL = api.Diagnostic.CRASH.ordinal | api.Diagnostic.ERROR.ordinal;
  final int INFO =
      api.Diagnostic.INFO.ordinal | api.Diagnostic.VERBOSE_INFO.ordinal;

  FormattingDiagnosticHandler([SourceFileProvider provider])
      : this.provider =
          (provider == null) ? new CompilerSourceFileProvider() : provider;

  void info(var message, [api.Diagnostic kind = api.Diagnostic.VERBOSE_INFO]) {
    if (!verbose && kind == api.Diagnostic.VERBOSE_INFO) return;
    if (enableColors) {
      print('${colors.green("Info:")} $message');
    } else {
      print('Info: $message');
    }
  }

  /// Adds [kind] specific prefix to [message].
  String prefixMessage(String message, api.Diagnostic kind) {
    switch (kind) {
      case api.Diagnostic.ERROR:
        return 'Error: $message';
      case api.Diagnostic.WARNING:
        return 'Warning: $message';
      case api.Diagnostic.HINT:
        return 'Hint: $message';
      case api.Diagnostic.CRASH:
        return 'Internal Error: $message';
      case api.Diagnostic.INFO:
      case api.Diagnostic.VERBOSE_INFO:
        return 'Info: $message';
    }
    throw 'Unexpected diagnostic kind: $kind (${kind.ordinal})';
  }

  @override
  void report(var code, Uri uri, int begin, int end, String message,
              api.Diagnostic kind) {
    // TODO(ahe): Remove this when source map is handled differently.
    if (identical(kind.name, 'source map')) return;

    if (isAborting) return;
    isAborting = (kind == api.Diagnostic.CRASH);

    bool fatal = (kind.ordinal & FATAL) != 0;
    bool isInfo = (kind.ordinal & INFO) != 0;
    if (isInfo && uri == null && kind != api.Diagnostic.INFO) {
      info(message, kind);
      return;
    }

    message = prefixMessage(message, kind);

    // [lastKind] records the previous non-INFO kind we saw.
    // This is used to suppress info about a warning when warnings are
    // suppressed, and similar for hints.
    if (kind != api.Diagnostic.INFO) {
      lastKind = kind;
    }
    var color;
    if (kind == api.Diagnostic.ERROR) {
      color = colors.red;
    } else if (kind == api.Diagnostic.WARNING) {
      if (!showWarnings) return;
      color = colors.magenta;
    } else if (kind == api.Diagnostic.HINT) {
      if (!showHints) return;
      color = colors.cyan;
    } else if (kind == api.Diagnostic.CRASH) {
      color = colors.red;
    } else if (kind == api.Diagnostic.INFO) {
      if (lastKind == api.Diagnostic.WARNING && !showWarnings) return;
      if (lastKind == api.Diagnostic.HINT && !showHints) return;
      color = colors.green;
    } else {
      throw 'Unknown kind: $kind (${kind.ordinal})';
    }
    if (!enableColors) {
      color = (x) => x;
    }
    if (uri == null) {
      print('${color(message)}');
    } else {
      SourceFile file = provider.sourceFiles[uri];
      if (file != null) {
        print(file.getLocationMessage(
          color(message), begin, end, colorize: color));
      } else {
        String position = end - begin > 0 ? '@$begin+${end - begin}' : '';
        print('${provider.relativizeUri(uri)}$position:\n'
              '${color(message)}');
      }
    }
    if (fatal && ++fatalCount >= throwOnErrorCount && throwOnError) {
      isAborting = true;
      throw new AbortLeg(message);
    }
  }

  // TODO(johnniwinther): Remove this when no longer needed for the old compiler
  // API.
  void call(Uri uri, int begin, int end, String message, api.Diagnostic kind) {
    return report(null, uri, begin, end, message, kind);
  }
}

typedef void MessageCallback(String message);

class RandomAccessFileOutputProvider {
  final Uri out;
  final Uri sourceMapOut;
  final MessageCallback onInfo;
  final MessageCallback onFailure;

  int totalCharactersWritten = 0;
  List<String> allOutputFiles = new List<String>();

  RandomAccessFileOutputProvider(this.out,
                                 this.sourceMapOut,
                                 {this.onInfo,
                                  this.onFailure});

  static Uri computePrecompiledUri(Uri out) {
    String extension = 'precompiled.js';
    String outPath = out.path;
    if (outPath.endsWith('.js')) {
      outPath = outPath.substring(0, outPath.length - 3);
      return out.resolve('$outPath.$extension');
    } else {
      return out.resolve(extension);
    }
  }

  EventSink<String> call(String name, String extension) {
    Uri uri;
    bool isPrimaryOutput = false;
    // TODO (johnniwinther, sigurdm): Make a better interface for
    // output-providers.
    if (extension == "deferred_map") {
      uri = out.resolve(name);
    } else if (name == '') {
      if (extension == 'js' || extension == 'dart') {
        isPrimaryOutput = true;
        uri = out;
      } else if (extension == 'precompiled.js') {
        uri = computePrecompiledUri(out);
        onInfo("File ($uri) is compatible with header"
               " \"Content-Security-Policy: script-src 'self'\"");
      } else if (extension == 'js.map' || extension == 'dart.map') {
        uri = sourceMapOut;
      } else if (extension == "info.json") {
        String outName = out.path.substring(out.path.lastIndexOf('/') + 1);
        uri = out.resolve('$outName.$extension');
      } else {
        onFailure('Unknown extension: $extension');
      }
    } else {
      uri = out.resolve('$name.$extension');
    }

    if (uri.scheme != 'file') {
      onFailure('Unhandled scheme ${uri.scheme} in $uri.');
    }

    RandomAccessFile output;
    try {
      output = new File(uri.toFilePath()).openSync(mode: FileMode.WRITE);
    } on FileSystemException catch(e) {
      onFailure('$e');
    }

    allOutputFiles.add(relativize(currentDirectory, uri, Platform.isWindows));

    int charactersWritten = 0;

    writeStringSync(String data) {
      // Write the data in chunks of 8kb, otherwise we risk running OOM.
      int chunkSize = 8*1024;

      int offset = 0;
      while (offset < data.length) {
        output.writeStringSync(
            data.substring(offset, math.min(offset + chunkSize, data.length)));
        offset += chunkSize;
      }
      charactersWritten += data.length;
    }

    onDone() {
      output.closeSync();
      if (isPrimaryOutput) {
        totalCharactersWritten += charactersWritten;
      }
    }

    return new EventSinkWrapper(writeStringSync, onDone);
  }
}

class EventSinkWrapper extends EventSink<String> {
  var onAdd, onClose;

  EventSinkWrapper(this.onAdd, this.onClose);

  void add(String data) => onAdd(data);

  void addError(error, [StackTrace stackTrace]) => throw error;

  void close() => onClose();
}
