// Copyright (c) 2015, 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.

import 'package:analyzer/file_system/file_system.dart' as resource;
import 'package:analyzer/file_system/memory_file_system.dart' as resource;
import 'package:analyzer/src/context/cache.dart'
    show AnalysisCache, CachePartition;
import 'package:analyzer/src/context/context.dart' show AnalysisContextImpl;
import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
import 'package:analyzer/src/generated/sdk.dart' show DartSdk, SdkLibrary;
import 'package:analyzer/src/generated/source.dart'
    show DartUriResolver, Source, SourceFactory;
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/summary_file_builder.dart';

/// Mock SDK for testing purposes.
class MockSdk implements DartSdk {
  static const String librariesContent = r'''
const Map<String, LibraryInfo> libraries = const {
  "async": const LibraryInfo("async/async.dart"),
  "collection": const LibraryInfo("collection/collection.dart"),
  "convert": const LibraryInfo("convert/convert.dart"),
  "core": const LibraryInfo("core/core.dart"),
  "io": const LibraryInfo("io/io.dart'"),
  "html": const LibraryInfo(
    "html/dartium/html_dartium.dart",
    dart2jsPath: "html/dart2js/html_dart2js.dart"),
  "math": const LibraryInfo("math/math.dart"),
};
''';

  static const _MockSdkLibrary LIB_CORE =
      const _MockSdkLibrary('dart:core', '/lib/core/core.dart', '''
library dart.core;

import 'dart:async';

class Object {
  const Object();

  bool operator ==(other) => identical(this, other);
  String toString() => 'a string';
  int get hashCode => 0;
}

class Function {}
class StackTrace {}
class Symbol {}
class Type {}

abstract class Comparable<T> {
  int compareTo(T other);
}

abstract class String extends Object implements Comparable<String> {
  external factory String.fromCharCodes(Iterable<int> charCodes,
                                        [int start = 0, int end]);
  bool get isEmpty => false;
  bool get isNotEmpty => false;
  int get length => 0;
  bool contains(String other, [int startIndex = 0]);
  int indexOf(String other, [int start]);
  String toUpperCase();
  List<int> get codeUnits;
}

class bool extends Object {}
abstract class num extends Object implements Comparable<num> {
  bool operator <(num other);
  bool operator <=(num other);
  bool operator >(num other);
  bool operator >=(num other);
  num operator +(num other);
  num operator -(num other);
  num operator *(num other);
  num operator /(num other);
  int toInt();
  num abs();
  int round();
}
abstract class int extends num {
  bool get isEven => false;
  int operator -();
  external static int parse(String source,
                            { int radix,
                              int onError(String source) });
}
class double extends num {}
class DateTime extends Object {
  DateTime.now() {}
  bool isBefore(DateTime other) => true;
}
class Null extends Object {}

class Deprecated extends Object {
  final String expires;
  const Deprecated(this.expires);
}
const Object deprecated = const Deprecated("next release");

class Error {
  Error();
  static String safeToString(Object object);
  external static String _stringToSafeString(String string);
  external static String _objectToString(Object object);
  external StackTrace get stackTrace;
}

class Iterator<E> {
  bool moveNext();
  E get current;
}

abstract class Iterable<E> {
  const Iterable();
  const factory Iterable.empty() = Iterable;
  Iterator<E> get iterator;
  bool contains(Object element);
  E firstWhere(bool test(E element), { E orElse()});
  bool get isEmpty;
  bool get isNotEmpty;
  E get first;
  E get last;
  int get length;
  Set<E> toSet() => new Set<E>.from(this);
}

abstract class List<E> implements Iterable<E> {
  /* external */ factory List([int length]);
  /* external */ factory List.filled(int length, E fill, {bool growable: false});
  void add(E value);
  E operator [](int index);
  void operator []=(int index, E value);
  Iterator<E> get iterator => null;
  void clear();
  int indexOf(Object element);
  bool get isEmpty;
  bool get isNotEmpty;
  Set<E> toSet() => new Set<E>.from(this);
}

abstract class Map<K, V> extends Object {
  /* external */ factory Map();
  factory Map.from(Map other) = LinkedHashMap<K, V>.from;
  factory Map.fromIterable(Iterable iterable,
      {K key(element), V value(element)}) = LinkedHashMap<K, V>.fromIterable;
  factory Map.fromIterables(Iterable<K> keys, Iterable<V> values) =
      LinkedHashMap<K, V>.fromIterables;    
  factory Map.of(Map<K, V> other) = LinkedHashMap<K, V>.of;
  factory Map.identity() = LinkedHashMap<K, V>.identity;
  /* external */ factory Map.unmodifiable(Map other);
  Iterable<K> get keys;
  bool get isEmpty;
  bool get isNotEmpty;
  int get length;
  V putIfAbsent(K key, V ifAbsent());
}

abstract class Set<E> implements Iterable<E> {
  Set<R> cast<R>();
  factory Set() = LinkedHashSet<E>;
  factory Set.identity() = LinkedHashSet<E>.identity;
  factory Set.from(Iterable elements) = LinkedHashSet<E>.from;
  factory Set.of(Iterable<E> elements) = LinkedHashSet<E>.of;
}

external bool identical(Object a, Object b);

void print(Object object) {}

class _Override {
  const _Override();
}
const Object override = const _Override();


abstract class RegExp {
  external factory RegExp(String source, {bool multiLine: false,
                                          bool caseSensitive: true});
}
''');

  static const _MockSdkLibrary LIB_ASYNC =
      const _MockSdkLibrary('dart:async', '/lib/async/async.dart', '''
library dart.async;

import 'dart:math';

class Stream<T> {}
abstract class StreamTransformer<S, T> {}

class Future<T> {
  factory Future.delayed(Duration duration, [T computation()]) => null;
  factory Future.value([value]) => null;
  static Future wait(List<Future> futures) => null;
}

class FutureOr<T> {}
''', const <_MockSdkFile>[
    const _MockSdkFile('/lib/async/stream.dart', r'''
part of dart.async;
''')
  ]);

  static const _MockSdkLibrary LIB_COLLECTION = const _MockSdkLibrary(
      'dart:collection', '/lib/collection/collection.dart', '''
library dart.collection;

abstract class HashMap<K, V> implements Map<K, V> {}
abstract class LinkedHashMap<K, V> implements Map<K, V> {
  /* external */ factory LinkedHashMap(
      {bool equals(K key1, K key2),
      int hashCode(K key),
      bool isValidKey(potentialKey)});
  /* external */ factory LinkedHashMap.identity();
  factory LinkedHashMap.from(Map other);
  factory LinkedHashMap.fromIterable(Iterable iterable,
      {K key(element), V value(element)});
  factory LinkedHashMap.fromIterables(Iterable<K> keys, Iterable<V> values);    
  factory LinkedHashMap.of(Map<K, V> other) =>
    new LinkedHashMap<K, V>()..addAll(other);
}
class LinkedHashSet<E> implements Set<E> {
  /* external factory */ LinkedHashSet(
      {bool equals(E e1, E e2),
      int hashCode(E e),
      bool isValidKey(potentialKey)});
  /* external factory */ LinkedHashSet.identity();
  factory LinkedHashSet.from(Iterable elements);
  
  factory LinkedHashSet.of(Iterable<E> elements) =>
      new LinkedHashSet<E>()..addAll(elements);
}
''');

  static const _MockSdkLibrary LIB_CONVERT =
      const _MockSdkLibrary('dart:convert', '/lib/convert/convert.dart', '''
library dart.convert;

import 'dart:async';

abstract class Converter<S, T> implements StreamTransformer {}
class JsonDecoder extends Converter<String, Object> {}
''');

  static const _MockSdkLibrary LIB_IO =
      const _MockSdkLibrary('dart:io', '/lib/io/io.dart', '''
library dart.io;

abstract class File implements FileSystemEntity {
  factory File(String path) => null;

  Future<DateTime> lastModified();
  DateTime lastModifiedSync();

  Future<bool> exists() async => true;
  bool existsSync() => true;

  Future<FileStat> stat() async => null;
  FileStat statSync() => null;
}

abstract class FileSystemEntity {
  static Future<bool> isDirectory(String path) => true;
  static bool isDirectorySync(String path) => true;

  static Future<bool> isFile(String path) => true;
  static bool isFileSync(String path) => true;

  static Future<bool> isLink(String path) => true;
  static bool isLinkSync(String path) => true;

  static Future<FileSystemEntityType> type(
    String path, {bool followLinks: true}) async => null;
  static FileSystemEntityType typeSync(
    String path, {bool followLinks: true}) => null;
}
''');

  static const _MockSdkLibrary LIB_MATH =
      const _MockSdkLibrary('dart:math', '/lib/math/math.dart', '''
library dart.math;
const double E = 2.718281828459045;
const double PI = 3.1415926535897932;
const double LN10 =  2.302585092994046;
num min(num a, num b) => 0;
num max(num a, num b) => 0;
external double cos(num x);
external double sin(num x);
external double sqrt(num x);
class Random {
  bool nextBool() => true;
  double nextDouble() => 2.0;
  int nextInt() => 1;
}
''');

  static const _MockSdkLibrary LIB_HTML = const _MockSdkLibrary(
      'dart:html', '/lib/html/dartium/html_dartium.dart', '''
library dart.html;
class HtmlElement {}
''');

  static const List<SdkLibrary> LIBRARIES = const [
    LIB_CORE,
    LIB_ASYNC,
    LIB_COLLECTION,
    LIB_CONVERT,
    LIB_IO,
    LIB_MATH,
    LIB_HTML,
  ];

  /// The cached linked bundle of the SDK.
  PackageBundle _bundle;

  final resource.MemoryResourceProvider provider;

  /// The [AnalysisContextImpl] which is used for all of the sources.
  AnalysisContextImpl _analysisContext;

  MockSdk(this.provider) {
    LIBRARIES.forEach((SdkLibrary library) {
      if (library is _MockSdkLibrary) {
        provider.newFile(provider.convertPath(library.path), library.content);
        library.parts.forEach((file) {
          provider.newFile(provider.convertPath(file.path), file.content);
        });
      }
    });
    provider.newFile(
        provider.convertPath(
            '/lib/_internal/sdk_library_metadata/lib/libraries.dart'),
        librariesContent);
  }

  @override
  AnalysisContextImpl get context {
    if (_analysisContext == null) {
      _analysisContext = new _SdkAnalysisContext(this);
      SourceFactory factory = new SourceFactory([new DartUriResolver(this)]);
      _analysisContext.sourceFactory = factory;
    }
    return _analysisContext;
  }

  @override
  List<SdkLibrary> get sdkLibraries => LIBRARIES;

  @override
  String get sdkVersion => throw unimplemented;

  UnimplementedError get unimplemented => new UnimplementedError();

  @override
  List<String> get uris =>
      sdkLibraries.map((SdkLibrary library) => library.shortName).toList();

  @override
  Source fromFileUri(Uri uri) {
    String filePath = provider.pathContext.fromUri(uri);
    if (!filePath.startsWith(provider.convertPath('/lib/'))) {
      return null;
    }
    for (SdkLibrary library in sdkLibraries) {
      String libraryPath = provider.convertPath(library.path);
      if (filePath == libraryPath) {
        try {
          resource.File file = provider.getResource(filePath);
          Uri dartUri = Uri.parse(library.shortName);
          return file.createSource(dartUri);
        } on FormatException {
          return null;
        }
      }
      String libraryRootPath = provider.pathContext.dirname(libraryPath) +
          provider.pathContext.separator;
      if (filePath.startsWith(libraryRootPath)) {
        String pathInLibrary = filePath.substring(libraryRootPath.length);
        String uriStr = '${library.shortName}/$pathInLibrary';
        try {
          resource.File file = provider.getResource(filePath);
          Uri dartUri = Uri.parse(uriStr);
          return file.createSource(dartUri);
        } on FormatException {
          return null;
        }
      }
    }
    return null;
  }

  @override
  PackageBundle getLinkedBundle() {
    if (_bundle == null) {
      resource.File summaryFile =
          provider.getFile(provider.convertPath('/lib/_internal/strong.sum'));
      List<int> bytes;
      if (summaryFile.exists) {
        bytes = summaryFile.readAsBytesSync();
      } else {
        bytes = _computeLinkedBundleBytes();
      }
      _bundle = new PackageBundle.fromBuffer(bytes);
    }
    return _bundle;
  }

  @override
  SdkLibrary getSdkLibrary(String dartUri) {
    for (SdkLibrary library in LIBRARIES) {
      if (library.shortName == dartUri) {
        return library;
      }
    }
    return null;
  }

  @override
  Source mapDartUri(String dartUri) {
    const Map<String, String> uriToPath = const {
      'dart:core': '/lib/core/core.dart',
      'dart:html': '/lib/html/dartium/html_dartium.dart',
      'dart:async': '/lib/async/async.dart',
      'dart:async/stream.dart': '/lib/async/stream.dart',
      'dart:collection': '/lib/collection/collection.dart',
      'dart:convert': '/lib/convert/convert.dart',
      'dart:io': '/lib/io/io.dart',
      'dart:math': '/lib/math/math.dart'
    };

    String path = uriToPath[dartUri];
    if (path != null) {
      resource.File file = provider.getResource(provider.convertPath(path));
      Uri uri = new Uri(scheme: 'dart', path: dartUri.substring(5));
      return file.createSource(uri);
    }

    // If we reach here then we tried to use a dartUri that's not in the
    // table above.
    return null;
  }

  /// Compute the bytes of the linked bundle associated with this SDK.
  List<int> _computeLinkedBundleBytes() {
    List<Source> librarySources = sdkLibraries
        .map((SdkLibrary library) => mapDartUri(library.shortName))
        .toList();
    return new SummaryBuilder(librarySources, context).build();
  }
}

class _MockSdkFile {
  final String path;
  final String content;

  const _MockSdkFile(this.path, this.content);
}

class _MockSdkLibrary implements SdkLibrary {
  @override
  final String shortName;
  @override
  final String path;
  final String content;
  final List<_MockSdkFile> parts;

  const _MockSdkLibrary(this.shortName, this.path, this.content,
      [this.parts = const <_MockSdkFile>[]]);

  @override
  String get category => throw new UnimplementedError();

  @override
  bool get isDart2JsLibrary => throw new UnimplementedError();

  @override
  bool get isDocumented => throw new UnimplementedError();

  @override
  bool get isImplementation => throw new UnimplementedError();

  @override
  bool get isInternal => shortName.startsWith('dart:_');

  @override
  bool get isShared => throw new UnimplementedError();

  @override
  bool get isVmLibrary => throw new UnimplementedError();
}

/// An [AnalysisContextImpl] that only contains sources for a Dart SDK.
class _SdkAnalysisContext extends AnalysisContextImpl {
  final DartSdk sdk;

  _SdkAnalysisContext(this.sdk);

  @override
  AnalysisCache createCacheFromSourceFactory(SourceFactory factory) {
    if (factory == null) {
      return super.createCacheFromSourceFactory(factory);
    }
    return new AnalysisCache(
        <CachePartition>[AnalysisEngine.instance.partitionManager.forSdk(sdk)]);
  }
}
