// Copyright (c) 2016, 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.
@JS()
library dev_compiler.web.web_command;

import 'dart:async';
import 'dart:convert';
import 'dart:math' as math;
import 'dart:html' show HttpRequest;
import 'dart:typed_data';

import 'package:analyzer/dart/element/element.dart'
    show
        LibraryElement,
        ImportElement,
        ShowElementCombinator,
        HideElementCombinator;
import 'package:analyzer/file_system/file_system.dart' show ResourceUriResolver;
import 'package:analyzer/file_system/memory_file_system.dart'
    show MemoryResourceProvider;
import 'package:analyzer/src/context/context.dart' show AnalysisContextImpl;
import 'package:analyzer/src/summary/idl.dart' show PackageBundle;
import 'package:analyzer/src/summary/package_bundle_reader.dart'
    show SummaryDataStore;
import 'package:analyzer/src/dart/resolver/scope.dart' show Scope;

import 'package:args/command_runner.dart';

import 'package:dev_compiler/src/analyzer/context.dart' show AnalyzerOptions;
import 'package:dev_compiler/src/analyzer/module_compiler.dart'
    show CompilerOptions, JSModuleFile, ModuleCompiler;

import 'package:dev_compiler/src/compiler/module_builder.dart';
import 'package:js/js.dart';
import 'package:path/path.dart' as path;

typedef void MessageHandler(Object message);

@JS()
@anonymous
class JSIterator<V> {}

@JS('Map')
class JSMap<K, V> {
  external V get(K v);
  external set(K k, V v);
  external JSIterator<K> keys();
  external JSIterator<V> values();
  external int get size;
}

@JS('Array.from')
external List<V> iteratorToList<V>(JSIterator<V> iterator);

@JS()
@anonymous
class CompileResult {
  external factory CompileResult(
      {String code, List<String> errors, bool isValid});
}

typedef CompileModule(String imports, String body, String libraryName,
    String existingLibrary, String fileName);

/// The command for invoking the modular compiler.
class WebCompileCommand extends Command {
  get name => 'compile';

  get description => 'Compile a set of Dart files into a JavaScript module.';
  final MessageHandler messageHandler;

  WebCompileCommand({MessageHandler messageHandler})
      : this.messageHandler = messageHandler ?? print {
    CompilerOptions.addArguments(argParser);
  }

  @override
  Function run() {
    return requestSummaries;
  }

  Future<Null> requestSummaries(String sdkUrl, JSMap<String, String> summaryMap,
      Function onCompileReady, Function onError, Function onProgress) async {
    var sdkRequest;
    var progress = 0;
    // Add 1 to the count for the SDK summary.
    var total = summaryMap.size + 1;
    // No need to report after every  summary is loaded. Posting about 100
    // progress updates should be more than sufficient for users to understand
    // how long loading will take.
    num progressDelta = math.max(total / 100, 1);
    num nextProgressToReport = 0;
    maybeReportProgress() {
      if (nextProgressToReport > progress && progress != total) return;
      nextProgressToReport += progressDelta;
      if (onProgress != null) onProgress(progress, total);
    }

    try {
      sdkRequest = await HttpRequest.request(sdkUrl,
          responseType: "arraybuffer",
          mimeType: "application/octet-stream",
          withCredentials: true);
    } catch (error) {
      onError('Dart sdk summaries failed to load: $error. url: $sdkUrl');
      return null;
    }
    progress++;
    maybeReportProgress();

    var sdkBytes = (sdkRequest.response as ByteBuffer).asUint8List();

    // Map summary URLs to HttpRequests.

    var summaryRequests =
        iteratorToList(summaryMap.values()).map((String summaryUrl) async {
      var request = await HttpRequest.request(summaryUrl,
          responseType: "arraybuffer", mimeType: "application/octet-stream");
      progress++;
      maybeReportProgress();
      return request;
    }).toList();
    try {
      var summaryResponses = await Future.wait(summaryRequests);
      // Map summary responses to summary bytes.
      List<List<int>> summaryBytes = summaryResponses
          .map((response) => (response.response as ByteBuffer).asUint8List())
          .toList();
      onCompileReady(setUpCompile(
          sdkBytes, summaryBytes, iteratorToList(summaryMap.keys())));
    } catch (error) {
      onError('Summaries failed to load: $error');
    }
  }

  List<Function> setUpCompile(List<int> sdkBytes, List<List<int>> summaryBytes,
      List<String> moduleIds) {
    var dartSdkSummaryPath = '/dart-sdk/lib/_internal/web_sdk.sum';

    var resources = MemoryResourceProvider()
      ..newFileWithBytes(dartSdkSummaryPath, sdkBytes);

    var options = AnalyzerOptions.basic(
        dartSdkPath: '/dart-sdk', dartSdkSummaryPath: dartSdkSummaryPath);

    var summaryData = SummaryDataStore([], resourceProvider: resources);
    var compilerOptions = CompilerOptions.fromArguments(argResults);
    compilerOptions.replCompile = true;
    for (var i = 0; i < summaryBytes.length; i++) {
      var bytes = summaryBytes[i];

      // Packages with no dart source files will have empty invalid summaries.
      if (bytes.length == 0) continue;

      var moduleId = moduleIds[i];
      var url = '/$moduleId.api.ds';
      summaryData.addBundle(url, PackageBundle.fromBuffer(bytes));
      compilerOptions.summaryModules[url] = moduleId;
    }

    var compiler = ModuleCompiler(options,
        analysisRoot: '/web-compile-root',
        fileResolvers: [ResourceUriResolver(resources)],
        resourceProvider: resources,
        summaryData: summaryData);

    var context = compiler.context as AnalysisContextImpl;

    var resolveFn = (String url) {
      var packagePrefix = 'package:';
      var uri = Uri.parse(url);
      var base = path.basename(url);
      var parts = uri.pathSegments;
      var match = null;
      int bestScore = 0;
      for (var candidate in summaryData.uriToSummaryPath.keys) {
        if (path.basename(candidate) != base) continue;
        List<String> candidateParts = path.dirname(candidate).split('/');
        var first = candidateParts.first;

        // Process and strip "package:" prefix.
        if (first.startsWith(packagePrefix)) {
          first = first.substring(packagePrefix.length);
          candidateParts[0] = first;
          // Handle convention that directory foo/bar/baz is given package name
          // foo.bar.baz
          if (first.contains('.')) {
            candidateParts = (first.split('.'))..addAll(candidateParts.skip(1));
          }
        }

        // If file name and extension don't match... give up.
        int i = parts.length - 1;
        int j = candidateParts.length - 1;

        int score = 1;
        // Greedy algorithm finding matching path segments from right to left
        // skipping segments on the candidate path unless the target path
        // segment is named lib.
        while (i >= 0 && j >= 0) {
          if (parts[i] == candidateParts[j]) {
            i--;
            j--;
            score++;
            if (j == 0 && i == 0) {
              // Arbitrary bonus if we matched all parts of the input
              // and used up all parts of the output.
              score += 10;
            }
          } else {
            // skip unmatched lib directories from the input
            // otherwise skip unmatched parts of the candidate.
            if (parts[i] == 'lib') {
              i--;
            } else {
              j--;
            }
          }
        }

        if (score > bestScore) {
          match = candidate;
        }
      }
      return match;
    };

    CompileModule compileFn = (String imports, String body, String libraryName,
        String existingLibrary, String fileName) {
      // Instead of returning a single function, return a pair of functions.
      // Create a new virtual File that contains the given Dart source.
      String sourceCode;
      if (existingLibrary == null) {
        sourceCode = imports + body;
      } else {
        var dir = path.dirname(existingLibrary);
        // Need to pull in all the imports from the existing library and
        // re-export all privates as privates in this library.
        var source = context.sourceFactory.forUri(existingLibrary);
        if (source == null) {
          throw "Unable to load source for library $existingLibrary";
        }

        LibraryElement libraryElement = context.computeLibraryElement(source);
        if (libraryElement == null) {
          throw "Unable to get library element.";
        }
        var sb = StringBuffer(imports);
        sb.write('\n');

        // TODO(jacobr): we need to add a proper Analyzer flag specifing that
        // cross-library privates should be in scope instead of this hack.
        // We set the private name prefix for scope resolution to an invalid
        // character code so that the analyzer ignores normal Dart private
        // scoping rules for top level names allowing REPL users to access
        // privates in arbitrary libraries. The downside of this scheme is it is
        // possible to get errors if privates in the current library and
        // imported libraries happen to have exactly the same name.
        Scope.PRIVATE_NAME_PREFIX = -1;

        // We emulate running code in the context of an existing library by
        // importing that library and all libraries it imports.
        sb.write('import ${json.encode(existingLibrary)};\n');

        for (ImportElement importElement in libraryElement.imports) {
          if (importElement.uri == null) continue;
          var uri = importElement.uri;
          // dart: and package: uris are not relative but the path package
          // thinks they are. We have to provide absolute uris as our library
          // has a different directory than the library we are pretending to be.
          if (path.isRelative(uri) &&
              !uri.startsWith('package:') &&
              !uri.startsWith('dart:')) {
            uri = path.normalize(path.join(dir, uri));
          }
          sb.write('import ${json.encode(uri)}');
          if (importElement.prefix != null)
            sb.write(' as ${importElement.prefix.name}');
          for (var combinator in importElement.combinators) {
            if (combinator is ShowElementCombinator) {
              sb.write(' show ${combinator.shownNames.join(', ')}');
            } else if (combinator is HideElementCombinator) {
              sb.write(' hide ${combinator.hiddenNames.join(', ')}');
            } else {
              throw 'Unexpected element combinator';
            }
          }
          sb.write(';\n');
        }
        sb.write(body);
        sourceCode = sb.toString();
      }
      resources.newFile(fileName, sourceCode);

      compilerOptions.moduleName = path.toUri(libraryName).toString();
      JSModuleFile module = compiler.compile([fileName], compilerOptions);

      var moduleCode = '';
      if (module.isValid) {
        var name = compilerOptions.moduleName;
        moduleCode =
            module.getCode(ModuleFormat.legacyConcat, name, name + '.map').code;
      }

      return CompileResult(
          code: moduleCode, isValid: module.isValid, errors: module.errors);
    };

    return [allowInterop(compileFn), allowInterop(resolveFn)];
  }
}

/// Thrown when the input source code has errors.
class CompileErrorException implements Exception {
  toString() => '\nPlease fix all errors before compiling (warnings are okay).';
}
