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

import 'dart:async';
import 'dart:collection';
import 'dart:convert';
import 'dart:typed_data';

import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/source/source_resource.dart';
import 'package:path/path.dart' as pathos;
import 'package:watcher/watcher.dart';

/// An in-memory implementation of [ResourceProvider].
/// Use `/` as a path separator.
class MemoryResourceProvider implements ResourceProvider {
  final Map<String, _MemoryResource> _pathToResource =
      HashMap<String, _MemoryResource>();
  final Map<String, Uint8List> _pathToBytes = HashMap<String, Uint8List>();
  final Map<String, int> _pathToTimestamp = HashMap<String, int>();
  final Map<String, String> _pathToLinkedPath = {};
  final Map<String, List<StreamController<WatchEvent>>> _pathToWatchers =
      HashMap<String, List<StreamController<WatchEvent>>>();
  int nextStamp = 0;

  final pathos.Context _pathContext;

  MemoryResourceProvider(
      {pathos.Context? context, @deprecated bool isWindows = false})
      : _pathContext = context ??= pathos.style == pathos.Style.windows
            // On Windows, ensure that the current drive matches
            // the drive inserted by MemoryResourceProvider.convertPath
            // so that packages are mapped to the correct drive
            ? pathos.Context(current: 'C:\\')
            : pathos.context;

  @override
  pathos.Context get pathContext => _pathContext;

  /// Convert the given posix [path] to conform to this provider's path context.
  ///
  /// This is a utility method for testing; paths passed in to other methods in
  /// this class are never converted automatically.
  String convertPath(String path) {
    if (pathContext.style == pathos.windows.style) {
      if (path.startsWith(pathos.posix.separator)) {
        path = r'C:' + path;
      }
      path = path.replaceAll(pathos.posix.separator, pathos.windows.separator);
    }
    return path;
  }

  /// Delete the file with the given path.
  void deleteFile(String path) {
    _checkFileAtPath(path);
    _pathToResource.remove(path);
    _pathToBytes.remove(path);
    _pathToTimestamp.remove(path);
    _notifyWatchers(path, ChangeType.REMOVE);
  }

  /// Delete the folder with the given path
  /// and recursively delete nested files and folders.
  void deleteFolder(String path) {
    _checkFolderAtPath(path);
    var folder = _pathToResource[path] as _MemoryFolder;
    for (Resource child in folder.getChildren()) {
      if (child is File) {
        deleteFile(child.path);
      } else if (child is Folder) {
        deleteFolder(child.path);
      } else {
        throw 'failed to delete resource: $child';
      }
    }
    _pathToResource.remove(path);
    _pathToBytes.remove(path);
    _pathToTimestamp.remove(path);
    _notifyWatchers(path, ChangeType.REMOVE);
  }

  @override
  File getFile(String path) {
    _ensureAbsoluteAndNormalized(path);
    return _MemoryFile(this, path);
  }

  @override
  Folder getFolder(String path) {
    _ensureAbsoluteAndNormalized(path);
    return _MemoryFolder(this, path);
  }

  @override
  Future<List<int>> getModificationTimes(List<Source> sources) async {
    return sources.map((source) {
      String path = source.fullName;
      return _pathToTimestamp[path] ?? -1;
    }).toList();
  }

  @override
  Resource getResource(String path) {
    _ensureAbsoluteAndNormalized(path);
    return _pathToResource[path] ?? _MemoryFile(this, path);
  }

  @override
  Folder getStateLocation(String pluginId) {
    var path = convertPath('/user/home/$pluginId');
    return newFolder(path);
  }

  void modifyFile(String path, String content) {
    _checkFileAtPath(path);
    _pathToBytes[path] = utf8.encode(content) as Uint8List;
    _pathToTimestamp[path] = nextStamp++;
    _notifyWatchers(path, ChangeType.MODIFY);
  }

  /// Create a resource representing a dummy link (that is, a File object which
  /// appears in its parent directory, but whose `exists` property is false)
  File newDummyLink(String path) {
    _ensureAbsoluteAndNormalized(path);
    newFolder(pathContext.dirname(path));
    _MemoryDummyLink link = _MemoryDummyLink(this, path);
    _pathToResource[path] = link;
    _pathToTimestamp[path] = nextStamp++;
    _notifyWatchers(path, ChangeType.ADD);
    return link;
  }

  File newFile(String path, String content, [int? stamp]) {
    _ensureAbsoluteAndNormalized(path);
    _MemoryFile file = _newFile(path);
    _pathToBytes[path] = utf8.encode(content) as Uint8List;
    _pathToTimestamp[path] = stamp ?? nextStamp++;
    _notifyWatchers(path, ChangeType.ADD);
    return file;
  }

  File newFileWithBytes(String path, List<int> bytes, [int? stamp]) {
    _ensureAbsoluteAndNormalized(path);
    _MemoryFile file = _newFile(path);
    _pathToBytes[path] = Uint8List.fromList(bytes);
    _pathToTimestamp[path] = stamp ?? nextStamp++;
    _notifyWatchers(path, ChangeType.ADD);
    return file;
  }

  Folder newFolder(String path) {
    _ensureAbsoluteAndNormalized(path);
    if (!pathContext.isAbsolute(path)) {
      throw ArgumentError("Path must be absolute : $path");
    }
    var resource = _pathToResource[path];
    if (resource == null) {
      String parentPath = pathContext.dirname(path);
      if (parentPath != path) {
        newFolder(parentPath);
      }
      _MemoryFolder folder = _MemoryFolder(this, path);
      _pathToResource[path] = folder;
      _pathToTimestamp[path] = nextStamp++;
      _notifyWatchers(path, ChangeType.ADD);
      return folder;
    } else if (resource is _MemoryFolder) {
      _notifyWatchers(path, ChangeType.ADD);
      return resource;
    } else {
      String message =
          'Folder expected at ' "'$path'" 'but ${resource.runtimeType} found';
      throw ArgumentError(message);
    }
  }

  /// Create a link from the [path] to the [target].
  void newLink(String path, String target) {
    _ensureAbsoluteAndNormalized(path);
    _ensureAbsoluteAndNormalized(target);
    _pathToLinkedPath[path] = target;
  }

  File updateFile(String path, String content, [int? stamp]) {
    _ensureAbsoluteAndNormalized(path);
    newFolder(pathContext.dirname(path));
    _MemoryFile file = _MemoryFile(this, path);
    _pathToResource[path] = file;
    _pathToBytes[path] = utf8.encode(content) as Uint8List;
    _pathToTimestamp[path] = stamp ?? nextStamp++;
    _notifyWatchers(path, ChangeType.MODIFY);
    return file;
  }

  /// Write a representation of the file system on the given [sink].
  void writeOn(StringSink sink) {
    List<String> paths = _pathToResource.keys.toList();
    paths.sort();
    paths.forEach(sink.writeln);
  }

  void _checkFileAtPath(String path) {
    // TODO(brianwilkerson) Consider throwing a FileSystemException rather than
    // an ArgumentError.
    var resource = _pathToResource[path];
    if (resource is! _MemoryFile) {
      if (resource == null) {
        throw ArgumentError('File expected at "$path" but does not exist');
      }
      throw ArgumentError(
          'File expected at "$path" but ${resource.runtimeType} found');
    }
  }

  void _checkFolderAtPath(String path) {
    // TODO(brianwilkerson) Consider throwing a FileSystemException rather than
    // an ArgumentError.
    var resource = _pathToResource[path];
    if (resource is! _MemoryFolder) {
      throw ArgumentError(
          'Folder expected at "$path" but ${resource.runtimeType} found');
    }
  }

  /// The file system abstraction supports only absolute and normalized paths.
  /// This method is used to validate any input paths to prevent errors later.
  void _ensureAbsoluteAndNormalized(String path) {
    if (!pathContext.isAbsolute(path)) {
      throw ArgumentError("Path must be absolute : $path");
    }
    if (pathContext.normalize(path) != path) {
      throw ArgumentError("Path must be normalized : $path");
    }
  }

  /// Create a new [_MemoryFile] without any content.
  _MemoryFile _newFile(String path) {
    String folderPath = pathContext.dirname(path);
    var folder = _pathToResource[folderPath];
    if (folder == null) {
      newFolder(folderPath);
    } else if (folder is! Folder) {
      throw ArgumentError('Cannot create file ($path) as child of file');
    }
    _MemoryFile file = _MemoryFile(this, path);
    _pathToResource[path] = file;
    return file;
  }

  void _notifyWatchers(String path, ChangeType changeType) {
    _pathToWatchers.forEach((String watcherPath,
        List<StreamController<WatchEvent>> streamControllers) {
      if (watcherPath == path || pathContext.isWithin(watcherPath, path)) {
        for (StreamController<WatchEvent> streamController
            in streamControllers) {
          streamController.add(WatchEvent(changeType, path));
        }
      }
    });
  }

  _MemoryFile _renameFileSync(_MemoryFile file, String newPath) {
    String path = file.path;
    if (newPath == path) {
      return file;
    }
    var existingNewResource = _pathToResource[newPath];
    if (existingNewResource is _MemoryFolder) {
      throw FileSystemException(
          path, 'Could not be renamed: $newPath is a folder.');
    }

    _MemoryFile newFile = _newFile(newPath);
    _pathToResource.remove(path);

    var oldBytes = _pathToBytes.remove(path);
    if (oldBytes != null) {
      _pathToBytes[newPath] = oldBytes;
    }

    var oldTimestamp = _pathToTimestamp.remove(path);
    if (oldTimestamp != null) {
      _pathToTimestamp[newPath] = oldTimestamp;
    }

    if (existingNewResource != null) {
      _notifyWatchers(newPath, ChangeType.REMOVE);
    }
    _notifyWatchers(path, ChangeType.REMOVE);
    _notifyWatchers(newPath, ChangeType.ADD);
    return newFile;
  }

  String _resolveLinks(String path) {
    var parentPath = _pathContext.dirname(path);
    if (parentPath == path) {
      return path;
    }

    var canonicalParentPath = _resolveLinks(parentPath);

    var baseName = _pathContext.basename(path);
    var result = _pathContext.join(canonicalParentPath, baseName);

    do {
      var linkTarget = _pathToLinkedPath[result];
      if (linkTarget != null) {
        result = linkTarget;
      } else {
        break;
      }
    } while (true);

    return result;
  }

  void _setFileContent(_MemoryFile file, List<int> bytes) {
    String path = file.path;
    _pathToResource[path] = file;
    _pathToBytes[path] = Uint8List.fromList(bytes);
    _pathToTimestamp[path] = nextStamp++;
    _notifyWatchers(path, ChangeType.MODIFY);
  }
}

/// An in-memory implementation of [File] which acts like a symbolic link to a
/// non-existent file.
class _MemoryDummyLink extends _MemoryResource implements File {
  _MemoryDummyLink(MemoryResourceProvider provider, String path)
      : super(provider, path);

  @override
  Stream<WatchEvent> get changes {
    throw FileSystemException(path, "File does not exist");
  }

  @override
  bool get exists => false;

  @override
  int get lengthSync {
    throw FileSystemException(path, 'File could not be read');
  }

  @override
  int get modificationStamp {
    var stamp = provider._pathToTimestamp[path];
    if (stamp == null) {
      throw FileSystemException(path, "File does not exist");
    }
    return stamp;
  }

  @override
  File copyTo(Folder parentFolder) {
    throw FileSystemException(path, 'File could not be copied');
  }

  @override
  Source createSource([Uri? uri]) {
    throw FileSystemException(path, 'File could not be read');
  }

  @override
  void delete() {
    throw FileSystemException(path, 'File could not be deleted');
  }

  @override
  bool isOrContains(String path) {
    return path == this.path;
  }

  @override
  Uint8List readAsBytesSync() {
    throw FileSystemException(path, 'File could not be read');
  }

  @override
  String readAsStringSync() {
    throw FileSystemException(path, 'File could not be read');
  }

  @override
  File renameSync(String newPath) {
    throw FileSystemException(path, 'File could not be renamed');
  }

  @override
  File resolveSymbolicLinksSync() {
    return throw FileSystemException(path, "File does not exist");
  }

  @override
  void writeAsBytesSync(List<int> bytes) {
    throw FileSystemException(path, 'File could not be written');
  }

  @override
  void writeAsStringSync(String content) {
    throw FileSystemException(path, 'File could not be written');
  }
}

/// An in-memory implementation of [File].
class _MemoryFile extends _MemoryResource implements File {
  _MemoryFile(MemoryResourceProvider provider, String path)
      : super(provider, path);

  @override
  bool get exists {
    var canonicalPath = provider._resolveLinks(path);
    return provider._pathToResource[canonicalPath] is _MemoryFile;
  }

  @override
  int get lengthSync {
    return readAsBytesSync().length;
  }

  @override
  int get modificationStamp {
    var canonicalPath = provider._resolveLinks(path);
    var stamp = provider._pathToTimestamp[canonicalPath];
    if (stamp == null) {
      throw FileSystemException(path, 'File "$path" does not exist.');
    }
    return stamp;
  }

  @override
  File copyTo(Folder parentFolder) {
    parentFolder.create();
    File destination = parentFolder.getChildAssumingFile(shortName);
    destination.writeAsBytesSync(readAsBytesSync());
    return destination;
  }

  @override
  Source createSource([Uri? uri]) {
    uri ??= provider.pathContext.toUri(path);
    return FileSource(this, uri);
  }

  @override
  void delete() {
    provider.deleteFile(path);
  }

  @override
  bool isOrContains(String path) {
    return path == this.path;
  }

  @override
  Uint8List readAsBytesSync() {
    var canonicalPath = provider._resolveLinks(path);
    var content = provider._pathToBytes[canonicalPath];
    if (content == null) {
      throw FileSystemException(path, 'File "$path" does not exist.');
    }
    return content;
  }

  @override
  String readAsStringSync() {
    var canonicalPath = provider._resolveLinks(path);
    var content = provider._pathToBytes[canonicalPath];
    if (content == null) {
      throw FileSystemException(path, 'File "$path" does not exist.');
    }
    return utf8.decode(content);
  }

  @override
  File renameSync(String newPath) {
    return provider._renameFileSync(this, newPath);
  }

  @override
  File resolveSymbolicLinksSync() {
    var canonicalPath = provider._resolveLinks(path);
    var result = provider.getFile(canonicalPath);

    if (!result.exists) {
      throw FileSystemException(path, 'File "$path" does not exist.');
    }

    return result;
  }

  @override
  void writeAsBytesSync(List<int> bytes) {
    provider._setFileContent(this, bytes);
  }

  @override
  void writeAsStringSync(String content) {
    provider._setFileContent(this, utf8.encode(content));
  }
}

/// An in-memory implementation of [Folder].
class _MemoryFolder extends _MemoryResource implements Folder {
  _MemoryFolder(MemoryResourceProvider provider, String path)
      : super(provider, path);

  @override
  bool get exists {
    var canonicalPath = provider._resolveLinks(path);
    return provider._pathToResource[canonicalPath] is _MemoryFolder;
  }

  @override
  bool get isRoot {
    var parentPath = provider.pathContext.dirname(path);
    return parentPath == path;
  }

  @override
  String canonicalizePath(String relPath) {
    relPath = provider.pathContext.normalize(relPath);
    String childPath = provider.pathContext.join(path, relPath);
    childPath = provider.pathContext.normalize(childPath);
    return childPath;
  }

  @override
  bool contains(String path) {
    return provider.pathContext.isWithin(this.path, path);
  }

  @override
  Folder copyTo(Folder parentFolder) {
    Folder destination = parentFolder.getChildAssumingFolder(shortName);
    destination.create();
    for (Resource child in getChildren()) {
      child.copyTo(destination);
    }
    return destination;
  }

  @override
  void create() {
    provider.newFolder(path);
  }

  @override
  void delete() {
    provider.deleteFolder(path);
  }

  @override
  Resource getChild(String relPath) {
    String childPath = canonicalizePath(relPath);
    return provider._pathToResource[childPath] ??
        _MemoryFile(provider, childPath);
  }

  @override
  _MemoryFile getChildAssumingFile(String relPath) {
    String childPath = canonicalizePath(relPath);
    var resource = provider._pathToResource[childPath];
    if (resource is _MemoryFile) {
      return resource;
    }
    return _MemoryFile(provider, childPath);
  }

  @override
  _MemoryFolder getChildAssumingFolder(String relPath) {
    String childPath = canonicalizePath(relPath);
    var resource = provider._pathToResource[childPath];
    if (resource is _MemoryFolder) {
      return resource;
    }
    return _MemoryFolder(provider, childPath);
  }

  @override
  List<Resource> getChildren() {
    var canonicalPath = provider._resolveLinks(path);
    if (canonicalPath != path) {
      var target = provider.getFolder(canonicalPath);
      var canonicalChildren = target.getChildren();
      return canonicalChildren.map((child) {
        var childPath = provider.pathContext.join(path, child.shortName);
        if (child is Folder) {
          return _MemoryFolder(provider, childPath);
        } else {
          return _MemoryFile(provider, childPath);
        }
      }).toList();
    }

    if (!exists) {
      throw FileSystemException(path, 'Folder does not exist.');
    }

    var children = <Resource>[];

    provider._pathToResource.forEach((resourcePath, resource) {
      if (provider.pathContext.dirname(resourcePath) == path) {
        children.add(resource);
      }
    });

    provider._pathToLinkedPath.forEach((resourcePath, targetPath) {
      if (provider.pathContext.dirname(resourcePath) == path) {
        var target = provider.getResource(targetPath);
        if (target is File) {
          children.add(
            _MemoryFile(provider, resourcePath),
          );
        } else if (target is Folder) {
          children.add(
            _MemoryFolder(provider, resourcePath),
          );
        }
      }
    });

    return children;
  }

  @override
  bool isOrContains(String path) {
    if (path == this.path) {
      return true;
    }
    return contains(path);
  }

  @override
  Folder resolveSymbolicLinksSync() {
    var canonicalPath = provider._resolveLinks(path);
    var result = provider.getFolder(canonicalPath);

    if (!result.exists) {
      throw FileSystemException(path, 'Folder "$path" does not exist.');
    }

    return result;
  }

  @override
  Uri toUri() => provider.pathContext.toUri(path + '/');
}

/// An in-memory implementation of [Resource].
abstract class _MemoryResource implements Resource {
  @override
  final MemoryResourceProvider provider;

  @override
  final String path;

  _MemoryResource(this.provider, this.path);

  Stream<WatchEvent> get changes {
    StreamController<WatchEvent> streamController =
        StreamController<WatchEvent>();
    if (!provider._pathToWatchers.containsKey(path)) {
      provider._pathToWatchers[path] = <StreamController<WatchEvent>>[];
    }
    provider._pathToWatchers[path]!.add(streamController);
    streamController.done.then((_) {
      provider._pathToWatchers[path]!.remove(streamController);
      if (provider._pathToWatchers[path]!.isEmpty) {
        provider._pathToWatchers.remove(path);
      }
    });
    return streamController.stream;
  }

  @override
  int get hashCode => path.hashCode;

  @Deprecated('Use parent2 instead')
  @override
  Folder? get parent {
    String parentPath = provider.pathContext.dirname(path);
    if (parentPath == path) {
      return null;
    }
    return provider.getFolder(parentPath);
  }

  @override
  Folder get parent2 {
    String parentPath = provider.pathContext.dirname(path);
    return provider.getFolder(parentPath);
  }

  @override
  String get shortName => provider.pathContext.basename(path);

  @override
  bool operator ==(Object other) {
    if (runtimeType != other.runtimeType) {
      return false;
    }
    return path == (other as _MemoryResource).path;
  }

  @override
  String toString() => path;

  @override
  Uri toUri() => provider.pathContext.toUri(path);
}
