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

library dart2js.serialization_helper;

import 'dart:async';
import 'dart:io';

import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/common/names.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/elements/elements.dart';

import '../memory_compiler.dart';
import 'test_data.dart';

const String DEFAULT_DATA_FILE_NAME = 'out.data';

class Arguments {
  final String filename;
  final int start;
  final int end;
  final bool loadSerializedData;
  final bool saveSerializedData;
  final String serializedDataFileName;
  final bool verbose;

  const Arguments({
    this.filename,
    this.start,
    this.end,
    this.loadSerializedData: false,
    this.saveSerializedData: false,
    this.serializedDataFileName: DEFAULT_DATA_FILE_NAME,
    this.verbose: false});

  factory Arguments.from(List<String> arguments) {
    String filename;
    int start;
    int end;
    for (String arg in arguments) {
      if (!arg.startsWith('-')) {
        int index = int.parse(arg, onError: (_) => null);
        if (index == null) {
          filename = arg;
        } else if (start == null) {
          start = index;
        } else {
          end = index;
        }
      }
    }
    bool verbose = arguments.contains('-v');
    bool loadSerializedData = arguments.contains('-l');
    bool saveSerializedData = arguments.contains('-s');
    if (arguments.contains('--auto')) {
      File file = new File(DEFAULT_DATA_FILE_NAME);
      if (file.existsSync()) {
        loadSerializedData = true;
      } else {
        saveSerializedData = true;
      }
    }
    return new Arguments(
        filename: filename,
        start: start,
        end: end,
        verbose: verbose,
        loadSerializedData: loadSerializedData,
        saveSerializedData: saveSerializedData);
  }

  Future forEachTest(
      SerializedData serializedData,
      List<Test> tests,
      TestFunction testFunction) async {
    Uri entryPoint = Uri.parse('memory:main.dart');
    int first = start ?? 0;
    int last = end ?? tests.length - 1;

    for (int index = first; index <= last; index++) {
      Test test = TESTS[index];
      List<SerializedData> dataList =
          await preserializeData(serializedData, test);
      Map<String, String> sourceFiles = <String, String>{};
      sourceFiles.addAll(test.sourceFiles);
      if (test.preserializedSourceFiles != null) {
        sourceFiles.addAll(test.preserializedSourceFiles);
      }
      if (test.unserializedSourceFiles != null) {
        sourceFiles.addAll(test.unserializedSourceFiles);
      }
      List<Uri> resolutionInputs = <Uri>[];
      for (SerializedData data in dataList) {
        data.expandMemorySourceFiles(sourceFiles);
        data.expandUris(resolutionInputs);
      }
      await testFunction(entryPoint,
          sourceFiles: sourceFiles,
          resolutionInputs: resolutionInputs,
          index: index,
          test: test,
          verbose: verbose);
    }
  }
}

typedef Future TestFunction(
    Uri entryPoint,
    {Map<String, String> sourceFiles,
     List<Uri> resolutionInputs,
     int index,
     Test test,
     bool verbose});

Future<SerializedData> serializeDartCore(
    {Arguments arguments: const Arguments()}) async {
  Uri uri = Uri.parse('memory:${arguments.serializedDataFileName}');
  print('------------------------------------------------------------------');
  print('serialize dart:core');
  print('------------------------------------------------------------------');
  SerializedData serializedData;
  if (arguments.loadSerializedData) {
    File file = new File(arguments.serializedDataFileName);
    if (file.existsSync()) {
      print('Loading data from $file');
      serializedData = new SerializedData(uri, file.readAsStringSync());
    }
  } else {
    SerializationResult result = await serialize(Uris.dart_core, dataUri: uri);
    serializedData = result.serializedData;
  }
  if (arguments.saveSerializedData) {
    File file = new File(arguments.serializedDataFileName);
    print('Saving data to $file');
    file.writeAsStringSync(serializedData.data);
  }
  return serializedData;
}

class SerializationResult {
  final Compiler compiler;
  final SerializedData serializedData;

  SerializationResult(this.compiler, this.serializedData);
}

Future<SerializationResult> serialize(Uri entryPoint,
    {Map<String, String> memorySourceFiles: const <String, String>{},
     List<Uri> resolutionInputs: const <Uri>[],
     Uri dataUri}) async {
  if (dataUri == null) {
    dataUri = Uri.parse('memory:${DEFAULT_DATA_FILE_NAME}');
  }
  Compiler compiler = compilerFor(
      options: [Flags.analyzeAll],
      memorySourceFiles: memorySourceFiles,
      resolutionInputs: resolutionInputs);
  compiler.serialization.supportSerialization = true;
  await compiler.run(entryPoint);
  BufferedEventSink sink = new BufferedEventSink();
  compiler.serialization.serializeToSink(
      sink, compiler.libraryLoader.libraries);
  SerializedData serializedData = new SerializedData(dataUri, sink.text);
  return new SerializationResult(compiler, serializedData);
}

class SerializedData {
  final Uri uri;
  final String data;

  SerializedData(this.uri, this.data);

  Map<String, String> toMemorySourceFiles([Map<String, String> input]) {
    Map<String, String> sourceFiles = <String, String>{};
    if (input != null) {
      sourceFiles.addAll(input);
    }
    expandMemorySourceFiles(sourceFiles);
    return sourceFiles;
  }

  void expandMemorySourceFiles(Map<String, String> sourceFiles) {
    if (uri.scheme == 'memory') {
      sourceFiles[uri.path] = data;
    }
  }

  List<Uri> toUris([List<Uri> input]) {
    List<Uri> uris = <Uri>[];
    if (input != null) {
      uris.addAll(input);
    }
    expandUris(uris);
    return uris;
  }

  void expandUris(List<Uri> uris) {
    uris.add(uri);
  }
}

String extractSerializedData(
    Compiler compiler, Iterable<LibraryElement> libraries) {
  BufferedEventSink sink = new BufferedEventSink();
  compiler.serialization.serializeToSink(sink, libraries);
  return sink.text;
}

Future<List<SerializedData>> preserializeData(
    SerializedData serializedData, Test test) async {
  if (test == null ||
      test.preserializedSourceFiles == null ||
      test.preserializedSourceFiles.isEmpty) {
    return <SerializedData>[serializedData];
  }
  List<Uri> uriList = <Uri>[];
  for (String key in test.preserializedSourceFiles.keys) {
    uriList.add(Uri.parse('memory:$key'));
  }
  Map<String, String> sourceFiles = serializedData.toMemorySourceFiles();
  sourceFiles.addAll(test.preserializedSourceFiles);
  if (test.unserializedSourceFiles != null) {
    sourceFiles.addAll(test.unserializedSourceFiles);
  }
  Compiler compiler = compilerFor(
      memorySourceFiles: sourceFiles,
      resolutionInputs: serializedData.toUris(),
      options: [Flags.analyzeOnly, Flags.analyzeMain]);
  compiler.librariesToAnalyzeWhenRun = uriList;
  compiler.serialization.supportSerialization = true;
  await compiler.run(null);
  List<LibraryElement> libraries = <LibraryElement>[];
  for (Uri uri in uriList) {
    libraries.add(compiler.libraryLoader.lookupLibrary(uri));
  }
  SerializedData additionalSerializedData =
      new SerializedData(Uri.parse('memory:additional.data'),
      extractSerializedData(compiler, libraries));
  return <SerializedData>[serializedData, additionalSerializedData];
}
