// Copyright (c) 2014, 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 trydart.poi;

import 'dart:async' show
    Completer,
    Future;

import 'dart:io' as io;

import 'dart:convert' show
    UTF8;

import 'package:dart2js_incremental/dart2js_incremental.dart' show
    INCREMENTAL_OPTIONS,
    reuseCompiler;

import 'package:dart2js_incremental/library_updater.dart' show
    IncrementalCompilerContext,
    LibraryUpdater;

import 'package:compiler/src/source_file_provider.dart' show
    FormattingDiagnosticHandler;

import 'package:compiler/compiler.dart' as api;

import 'package:compiler/src/dart2jslib.dart' show
    Compiler,
    CompilerTask,
    Enqueuer,
    QueueFilter,
    WorkItem;

import 'package:compiler/src/elements/visitor.dart' show
    ElementVisitor;

import 'package:compiler/src/elements/elements.dart' show
    AbstractFieldElement,
    ClassElement,
    CompilationUnitElement,
    Element,
    ElementCategory,
    FunctionElement,
    LibraryElement,
    ScopeContainerElement;

import 'package:compiler/src/elements/modelx.dart' as modelx;

import 'package:compiler/src/elements/modelx.dart' show
    DeclarationSite;

import 'package:compiler/src/dart_types.dart' show
    DartType;

import 'package:compiler/src/scanner/scannerlib.dart' show
    EOF_TOKEN,
    IDENTIFIER_TOKEN,
    KEYWORD_TOKEN,
    PartialClassElement,
    PartialElement,
    Token;

import 'package:compiler/src/js/js.dart' show
    js;

import 'scope_information_visitor.dart' show
    ScopeInformationVisitor;

/// Enabled by the option --enable-dart-mind.  Controls if this program should
/// be querying Dart Mind.
bool isDartMindEnabled = false;

/// Iterator over lines from standard input (or the argument array).
Iterator<String> stdin;

/// Enabled by the option --simulate-mutation. When true, this program will
/// only prompt for one file name, and subsequent runs will read
/// FILENAME.N.dart, where N starts at 1, and is increased on each iteration.
/// For example, if the program is invoked as:
///
///   dart poi.dart --simulate-mutation test.dart 11 22 33 44
///
/// The program will first read the file 'test.dart' and compute scope
/// information about position 11, then position 22 in test.dart.1.dart, then
/// position 33 in test.dart.2.dart, and finally position 44 in
/// test.dart.3.dart.
bool isSimulateMutationEnabled = false;

/// Counts the number of times [runPoi] has been invoked.
int poiCount;

int globalCounter = 0;

/// Enabled by the option --verbose (or -v). Prints more information than you
/// really need.
bool isVerbose = false;

/// Enabled by the option --compile. Also compiles the program after analyzing
/// the POI.
bool isCompiler = false;

/// Enabled by the option --minify. Passes the same option to the compiler to
/// generate minified output.
bool enableMinification = false;

/// When true (the default value) print serialized scope information at the
/// provided position.
const bool PRINT_SCOPE_INFO =
    const bool.fromEnvironment('PRINT_SCOPE_INFO', defaultValue: true);

Stopwatch wallClock = new Stopwatch();

PoiTask poiTask;

Compiler cachedCompiler;

/// Iterator for reading lines from [io.stdin].
class StdinIterator implements Iterator<String> {
  String current;

  bool moveNext() {
    current = io.stdin.readLineSync();
    return true;
  }
}

printFormattedTime(message, int us) {
  String m = '$message${" " * 65}'.substring(0, 60);
  String i = '${" " * 10}${(us/1000).toStringAsFixed(3)}';
  i = i.substring(i.length - 10);
  print('$m ${i}ms');
}

printWallClock(message) {
  if (!isVerbose) return;
  if (wallClock.isRunning) {
    print('$message');
    printFormattedTime('--->>>', wallClock.elapsedMicroseconds);
    wallClock.reset();
  } else {
    print(message);
  }
}

printVerbose(message) {
  if (!isVerbose) return;
  print(message);
}

main(List<String> arguments) {
  poiCount = 0;
  wallClock.start();
  List<String> nonOptionArguments = [];
  for (String argument in arguments) {
    if (argument.startsWith('-')) {
      switch (argument) {
        case '--simulate-mutation':
          isSimulateMutationEnabled = true;
          break;
        case '--enable-dart-mind':
          isDartMindEnabled = true;
          break;
        case '-v':
        case '--verbose':
          isVerbose = true;
          break;
        case '--compile':
          isCompiler = true;
          break;
        case '--minify':
          enableMinification = true;
          break;
        default:
          throw 'Unknown option: $argument.';
      }
    } else {
      nonOptionArguments.add(argument);
    }
  }
  if (nonOptionArguments.isEmpty) {
    stdin = new StdinIterator();
  } else {
    stdin = nonOptionArguments.iterator;
  }

  FormattingDiagnosticHandler handler = new FormattingDiagnosticHandler();
  handler
      ..verbose = false
      ..enableColors = true;
  api.CompilerInputProvider inputProvider = handler.provider;

  return prompt('Dart file: ').then((String fileName) {
    if (isSimulateMutationEnabled) {
      inputProvider = simulateMutation(fileName, inputProvider);
    }
    return prompt('Position: ').then((String position) {
      return parseUserInput(fileName, position, inputProvider, handler);
    });
  });
}

/// Create an input provider that implements the behavior documented at
/// [simulateMutation].
api.CompilerInputProvider simulateMutation(
    String fileName,
    api.CompilerInputProvider inputProvider) {
  Uri script = Uri.base.resolveUri(new Uri.file(fileName));
  int count = poiCount;
  Future cache;
  String cachedFileName = script.toFilePath();
  int counter = ++globalCounter;
  return (Uri uri) {
    if (counter != globalCounter) throw 'Using old provider';
    printVerbose('fake inputProvider#$counter($uri): $poiCount $count');
    if (uri == script) {
      if (poiCount == count) {
        cachedFileName = uri.toFilePath();
        if (count != 0) {
          cachedFileName = '$cachedFileName.$count.dart';
        }
        printVerbose('Not using cached version of $cachedFileName');
        cache = new io.File(cachedFileName).readAsBytes().then((data) {
          printVerbose(
              'Read file $cachedFileName: '
              '${UTF8.decode(data.take(100).toList(), allowMalformed: true)}...');
          return data;
        });
        count++;
      } else {
        printVerbose('Using cached version of $cachedFileName');
      }
      return cache;
    } else {
      printVerbose('Using original provider for $uri');
      return inputProvider(uri);
    }
  };
}

Future<String> prompt(message) {
  if (stdin is StdinIterator) {
    io.stdout.write(message);
  }
  return io.stdout.flush().then((_) {
    stdin.moveNext();
    return stdin.current;
  });
}

Future queryDartMind(String prefix, String info) {
  // TODO(lukechurch): Use [info] for something.
  String encodedArg0 = Uri.encodeComponent('"$prefix"');
  String mindQuery =
      'http://dart-mind.appspot.com/rpc'
      '?action=GetExportingPubCompletions'
      '&arg0=$encodedArg0';
  Uri uri = Uri.parse(mindQuery);

  io.HttpClient client = new io.HttpClient();
  return client.getUrl(uri).then((io.HttpClientRequest request) {
    return request.close();
  }).then((io.HttpClientResponse response) {
    Completer<String> completer = new Completer<String>();
    response.transform(UTF8.decoder).listen((contents) {
      completer.complete(contents);
    });
    return completer.future;
  });
}

Future parseUserInput(
    String fileName,
    String positionString,
    api.CompilerInputProvider inputProvider,
    api.DiagnosticHandler handler) {
  Future repeat() {
    printFormattedTime('--->>>', wallClock.elapsedMicroseconds);
    wallClock.reset();

    return prompt('Position: ').then((String positionString) {
      wallClock.reset();
      return parseUserInput(fileName, positionString, inputProvider, handler);
    });
  }

  printWallClock("\n\n\nparseUserInput('$fileName', '$positionString')");

  Uri script = Uri.base.resolveUri(new Uri.file(fileName));
  if (positionString == null) return null;
  int position = int.parse(
      positionString, onError: (_) { print('Please enter an integer.'); });
  if (position == null) return repeat();

  inputProvider(script);
  if (isVerbose) {
    handler(
        script, position, position + 1,
        'Point of interest. '
        'Cursor is immediately before highlighted character.',
        api.Diagnostic.HINT);
  }

  Stopwatch sw = new Stopwatch()..start();

  Future future = runPoi(script, position, inputProvider, handler);
  return future.then((Element element) {
    if (isVerbose) {
      printFormattedTime('Resolving took', sw.elapsedMicroseconds);
    }
    sw.reset();
    String info = scopeInformation(element, position);
    sw.stop();
    if (PRINT_SCOPE_INFO) {
      print(info);
    }
    printVerbose('Scope information took ${sw.elapsedMicroseconds}us.');
    sw..reset()..start();
    Token token = findToken(element, position);
    String prefix;
    if (token != null) {
      if (token.charOffset + token.charCount <= position) {
        // After the token; in whitespace, or in the beginning of another token.
        prefix = "";
      } else if (token.kind == IDENTIFIER_TOKEN ||
                 token.kind == KEYWORD_TOKEN) {
        prefix = token.value.substring(0, position - token.charOffset);
      }
    }
    sw.stop();
    printVerbose('Find token took ${sw.elapsedMicroseconds}us.');
    if (isDartMindEnabled && prefix != null) {
      sw..reset()..start();
      return queryDartMind(prefix, info).then((String dartMindSuggestion) {
        sw.stop();
        print('Dart Mind ($prefix): $dartMindSuggestion.');
        printVerbose('Dart Mind took ${sw.elapsedMicroseconds}us.');
        return repeat();
      });
    } else {
      if (isDartMindEnabled) {
        print("Didn't talk to Dart Mind, no identifier at POI ($token).");
      }
      return repeat();
    }
  });
}

/// Find the token corresponding to [position] in [element].  The method only
/// works for instances of [PartialElement] or [LibraryElement].  Support for
/// [LibraryElement] is currently limited, and works only for named libraries.
Token findToken(modelx.ElementX element, int position) {
  Token beginToken;
  DeclarationSite site = element.declarationSite;
  if (site is PartialElement) {
    beginToken = site.beginToken;
  } else if (element.isLibrary) {
    // TODO(ahe): Generalize support for library elements (and update above
    // documentation).
    modelx.LibraryElementX lib = element;
    var tag = lib.libraryTag;
    if (tag != null) {
      beginToken = tag.libraryKeyword;
    }
  } else {
    beginToken = element.position;
  }
  if (beginToken == null) return null;
  for (Token token = beginToken; token.kind != EOF_TOKEN; token = token.next) {
    if (token.charOffset < position && position <= token.next.charOffset) {
      return token;
    }
  }
  return null;
}

Future<Element> runPoi(
    Uri script,
    int position,
    api.CompilerInputProvider inputProvider,
    api.DiagnosticHandler handler) {
  Stopwatch sw = new Stopwatch()..start();
  Uri libraryRoot = Uri.base.resolve('sdk/');
  Uri packageRoot = Uri.base.resolveUri(
      new Uri.file('${io.Platform.packageRoot}/'));

  var options = [
      '--analyze-main',
      '--verbose',
      '--categories=Client,Server',
  ];
  options.addAll(INCREMENTAL_OPTIONS);

  if (!isCompiler) {
    options.add('--analyze-only');
  }

  if (enableMinification) {
    options.add('--minify');
  }

  LibraryUpdater updater;

  Future<bool> reuseLibrary(LibraryElement library) {
    return poiTask.measure(() => updater.reuseLibrary(library));
  }

  Future<Compiler> invokeReuseCompiler() {
    var context = new IncrementalCompilerContext();
    updater = new LibraryUpdater(
        cachedCompiler, inputProvider, printWallClock, printVerbose, context);
    context.registerUriWithUpdates([script]);
    return reuseCompiler(
        diagnosticHandler: handler,
        inputProvider: inputProvider,
        options: options,
        cachedCompiler: cachedCompiler,
        libraryRoot: libraryRoot,
        packageRoot: packageRoot,
        packagesAreImmutable: true,
        reuseLibrary: reuseLibrary);
  }

  return invokeReuseCompiler().then((Compiler newCompiler) {
    // TODO(ahe): Move this "then" block to [reuseCompiler].
    if (updater.failed) {
      cachedCompiler = null;
      return invokeReuseCompiler();
    } else {
      return newCompiler;
    }
  }).then((Compiler newCompiler) {
    if (!isCompiler) {
      newCompiler.enqueuerFilter = new ScriptOnlyFilter(script);
    }
    return runPoiInternal(newCompiler, sw, updater, script, position);
  });
}

Future<Element> runPoiInternal(
    Compiler newCompiler,
    Stopwatch sw,
    LibraryUpdater updater,
    Uri uri,
    int position) {
  bool isFullCompile = cachedCompiler != newCompiler;
  cachedCompiler = newCompiler;
  if (poiTask == null || poiTask.compiler != cachedCompiler) {
    poiTask = new PoiTask(cachedCompiler);
    cachedCompiler.tasks.add(poiTask);
  }

  if (!isFullCompile) {
    printFormattedTime(
        'Analyzing changes and updating elements took', sw.elapsedMicroseconds);
  }
  sw.reset();

  Future<bool> compilation;

  if (updater.hasPendingUpdates) {
    compilation = new Future(() {
      var node = js.statement(
          r'var $dart_patch = #', js.escapedString(updater.computeUpdateJs()));
      print(updater.prettyPrintJs(node));

      return !cachedCompiler.compilationFailed;
    });
  } else {
    compilation = cachedCompiler.run(uri);
  }

  return compilation.then((success) {
    printVerbose('Compiler queue processed in ${sw.elapsedMicroseconds}us');
    if (isVerbose) {
      for (final task in cachedCompiler.tasks) {
        int time = task.timingMicroseconds;
        if (time != 0) {
          printFormattedTime('${task.name} took', time);
        }
      }
    }

    if (poiCount != null) poiCount++;
    if (success != true) {
      throw 'Compilation failed';
    }
    return findPosition(position, cachedCompiler.mainApp);
  });
}

Element findPosition(int position, Element element) {
  FindPositionVisitor visitor = new FindPositionVisitor(position, element);
  element.accept(visitor);
  return visitor.element;
}

String scopeInformation(Element element, int position) {
  ScopeInformationVisitor visitor =
      new ScopeInformationVisitor(cachedCompiler, element, position);
  element.accept(visitor);
  return '${visitor.buffer}';
}

class FindPositionVisitor extends ElementVisitor {
  final int position;
  Element element;

  FindPositionVisitor(this.position, this.element);

  visitElement(modelx.ElementX e) {
    DeclarationSite site = e.declarationSite;
    if (site is PartialElement) {
      if (site.beginToken.charOffset <= position &&
          position < site.endToken.next.charOffset) {
        element = e;
      }
    }
  }

  visitClassElement(ClassElement e) {
    if (e is PartialClassElement) {
      if (e.beginToken.charOffset <= position &&
          position < e.endToken.next.charOffset) {
        element = e;
        visitScopeContainerElement(e);
      }
    }
  }

  visitScopeContainerElement(ScopeContainerElement e) {
    e.forEachLocalMember((Element element) => element.accept(this));
  }
}

class ScriptOnlyFilter implements QueueFilter {
  final Uri script;

  ScriptOnlyFilter(this.script);

  bool checkNoEnqueuedInvokedInstanceMethods(Enqueuer enqueuer) => true;

  void processWorkItem(void f(WorkItem work), WorkItem work) {
    if (work.element.library.canonicalUri != script) {
      // TODO(ahe): Rather nasty hack to work around another nasty hack in
      // backend.dart. Find better solution.
      if (work.element.name != 'closureFromTearOff') {
        printWallClock('Skipped ${work.element}.');
        return;
      }
    }
    f(work);
    printWallClock('Processed ${work.element}.');
  }
}

class PoiTask extends CompilerTask {
  PoiTask(Compiler compiler) : super(compiler);

  String get name => 'POI';
}
