// Copyright (c) 2018, 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:convert';
import 'dart:core';
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:meta/meta.dart';
import 'package:path/path.dart' as pathos;
import 'package:watcher/watcher.dart';

/**
 * A resource provider that allows clients to overlay the file system provided
 * by a base resource provider. These overlays allow both the contents and
 * modification stamps of files to be different than what the base resource
 * provider would report.
 *
 * This provider does not report watch events when overlays are added, modified
 * or removed.
 */
class OverlayResourceProvider implements ResourceProvider {
  /**
   * The underlying resource provider used to access files and folders that
   * do not have an overlay.
   */
  final ResourceProvider baseProvider;

  /**
   * A map from the paths of files for which there is an overlay to the contents
   * of the files.
   */
  final Map<String, String> _overlayContent = <String, String>{};

  /**
   * A map from the paths of files for which there is an overlay to the
   * modification stamps of the files.
   */
  final Map<String, int> _overlayModificationStamps = <String, int>{};

  /**
   * Initialize a newly created resource provider to represent an overlay on the
   * given [baseProvider].
   */
  OverlayResourceProvider(this.baseProvider);

  @override
  pathos.Context get pathContext => baseProvider.pathContext;

  @override
  File getFile(String path) =>
      new _OverlayFile(this, baseProvider.getFile(path));

  @override
  Folder getFolder(String path) =>
      new _OverlayFolder(this, baseProvider.getFolder(path));

  @override
  Future<List<int>> getModificationTimes(List<Source> sources) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    return sources.map((source) {
      String path = source.fullName;
      return _overlayModificationStamps[path] ??
          baseProvider.getFile(path).modificationStamp;
    }).toList();
  }

  @override
  Resource getResource(String path) {
    if (hasOverlay(path)) {
      return new _OverlayResource._from(this, baseProvider.getFile(path));
    } else if (_hasOverlayIn(path)) {
      return new _OverlayResource._from(this, baseProvider.getFolder(path));
    }
    return new _OverlayResource._from(this, baseProvider.getResource(path));
  }

  @override
  Folder getStateLocation(String pluginId) =>
      new _OverlayFolder(this, baseProvider.getStateLocation(pluginId));

  /**
   * Return `true` if there is an overlay associated with the file at the given
   * [path].
   */
  bool hasOverlay(String path) => _overlayContent.containsKey(path);

  /**
   * Remove any overlay of the file at the given [path]. The state of the file
   * in the base resource provider will not be affected.
   */
  bool removeOverlay(String path) {
    bool hadOverlay = _overlayContent.containsKey(path);
    _overlayContent.remove(path);
    _overlayModificationStamps.remove(path);
    return hadOverlay;
  }

  /**
   * Overlay the content of the file at the given [path]. The file will appear
   * to have the given [content] and [modificationStamp] even if the file is
   * modified in the base resource provider.
   */
  void setOverlay(String path,
      {@required String content, @required int modificationStamp}) {
    if (content == null) {
      throw new ArgumentError(
          'OverlayResourceProvider.setOverlay: content cannot be null');
    } else if (modificationStamp == null) {
      throw new ArgumentError(
          'OverlayResourceProvider.setOverlay: modificationStamp cannot be null');
    }
    _overlayContent[path] = content;
    _overlayModificationStamps[path] = modificationStamp;
  }

  /**
   * Copy any overlay for the file at the [oldPath] to be an overlay for the
   * file with the [newPath].
   */
  void _copyOverlay(String oldPath, String newPath) {
    if (hasOverlay(oldPath)) {
      _overlayContent[newPath] = _overlayContent[oldPath];
      _overlayModificationStamps[newPath] = _overlayModificationStamps[oldPath];
    }
  }

  /**
   * Return the content of the overlay of the file at the given [path], or
   * `null` if there is no overlay for the specified file.
   */
  String _getOverlayContent(String path) {
    return _overlayContent[path];
  }

  /**
   * Return the modification stamp of the overlay of the file at the given
   * [path], or `null` if there is no overlay for the specified file.
   */
  int _getOverlayModificationStamp(String path) {
    return _overlayModificationStamps[path];
  }

  /**
   * Return `true` if there is an overlay associated with at least one file
   * contained inside the folder with the given [folderPath].
   */
  bool _hasOverlayIn(String folderPath) => _overlayContent.keys
      .any((filePath) => pathContext.isWithin(folderPath, filePath));

  /**
   * Return the paths of all of the overlaid files that are children of the
   * given [folder], either directly or indirectly.
   */
  Iterable<String> _overlaysInFolder(String folderPath) => _overlayContent.keys
      .where((filePath) => pathContext.isWithin(folderPath, filePath));
}

/**
 * A file from an [OverlayResourceProvider].
 */
class _OverlayFile extends _OverlayResource implements File {
  /**
   * Initialize a newly created file to have the given [provider] and to
   * correspond to the given [file] from the provider's base resource provider.
   */
  _OverlayFile(OverlayResourceProvider provider, File file)
      : super(provider, file);

  @override
  Stream<WatchEvent> get changes => _file.changes;

  @override
  bool get exists => _provider.hasOverlay(path) || _resource.exists;

  @override
  int get lengthSync {
    String content = _provider._getOverlayContent(path);
    if (content != null) {
      return content.length;
    }
    return _file.lengthSync;
  }

  @override
  int get modificationStamp {
    int stamp = _provider._getOverlayModificationStamp(path);
    if (stamp != null) {
      return stamp;
    }
    return _file.modificationStamp;
  }

  /**
   * Return the file from the base resource provider that corresponds to this
   * folder.
   */
  File get _file => _resource as File;

  @override
  File copyTo(Folder parentFolder) {
    String newPath = _provider.pathContext.join(parentFolder.path, shortName);
    _provider._copyOverlay(path, newPath);
    if (_file.exists) {
      if (parentFolder is _OverlayFolder) {
        return new _OverlayFile(_provider, _file.copyTo(parentFolder._folder));
      }
      return new _OverlayFile(_provider, _file.copyTo(parentFolder));
    } else {
      return new _OverlayFile(
          _provider, _provider.baseProvider.getFile(newPath));
    }
  }

  @override
  Source createSource([Uri uri]) =>
      new FileSource(this, uri ?? _provider.pathContext.toUri(path));

  @override
  void delete() {
    bool hadOverlay = _provider.removeOverlay(path);
    if (_resource.exists) {
      _resource.delete();
    } else if (!hadOverlay) {
      throw new FileSystemException(path, 'does not exist');
    }
  }

  @override
  Uint8List readAsBytesSync() {
    String content = _provider._getOverlayContent(path);
    if (content != null) {
      return utf8.encode(content) as Uint8List;
    }
    return _file.readAsBytesSync();
  }

  @override
  String readAsStringSync() {
    String content = _provider._getOverlayContent(path);
    if (content != null) {
      return content;
    }
    return _file.readAsStringSync();
  }

  @override
  File renameSync(String newPath) {
    File newFile = _file.renameSync(newPath);
    if (_provider.hasOverlay(path)) {
      _provider.setOverlay(newPath,
          content: _provider._getOverlayContent(path),
          modificationStamp: _provider._getOverlayModificationStamp(path));
      _provider.removeOverlay(path);
    }
    return new _OverlayFile(_provider, newFile);
  }

  @override
  void writeAsBytesSync(List<int> bytes) {
    writeAsStringSync(new String.fromCharCodes(bytes));
  }

  @override
  void writeAsStringSync(String content) {
    if (_provider.hasOverlay(path)) {
      throw new FileSystemException(
          path, 'Cannot write a file with an overlay');
    }
    _file.writeAsStringSync(content);
  }
}

/**
 * A folder from an [OverlayResourceProvider].
 */
class _OverlayFolder extends _OverlayResource implements Folder {
  /**
   * Initialize a newly created folder to have the given [provider] and to
   * correspond to the given [folder] from the provider's base resource
   * provider.
   */
  _OverlayFolder(OverlayResourceProvider provider, Folder folder)
      : super(provider, folder);

  @override
  Stream<WatchEvent> get changes => _folder.changes;

  @override
  bool get exists => _provider._hasOverlayIn(path) || _resource.exists;

  /**
   * Return the folder from the base resource provider that corresponds to this
   * folder.
   */
  Folder get _folder => _resource as Folder;

  @override
  String canonicalizePath(String relPath) {
    pathos.Context context = _provider.pathContext;
    relPath = context.normalize(relPath);
    String childPath = context.join(path, relPath);
    childPath = context.normalize(childPath);
    return childPath;
  }

  @override
  bool contains(String path) => _folder.contains(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() {
    _folder.create();
  }

  @override
  Resource getChild(String relPath) =>
      new _OverlayResource._from(_provider, _folder.getChild(relPath));

  @override
  File getChildAssumingFile(String relPath) =>
      new _OverlayFile(_provider, _folder.getChildAssumingFile(relPath));

  @override
  Folder getChildAssumingFolder(String relPath) =>
      new _OverlayFolder(_provider, _folder.getChildAssumingFolder(relPath));

  @override
  List<Resource> getChildren() {
    Map<String, Resource> children = {};
    try {
      for (final child in _folder.getChildren()) {
        children[child.path] = new _OverlayResource._from(_provider, child);
      }
    } on FileSystemException {
      // We don't want to throw if we're a folder that only exists in the overlay
      // and not on disk.
    }

    for (String overlayPath in _provider._overlaysInFolder(path)) {
      pathos.Context context = _provider.pathContext;
      if (context.dirname(overlayPath) == path) {
        children.putIfAbsent(overlayPath, () => _provider.getFile(overlayPath));
      } else {
        String relativePath = context.relative(overlayPath, from: path);
        String folderName = context.split(relativePath)[0];
        String folderPath = context.join(path, folderName);
        children.putIfAbsent(folderPath, () => _provider.getFolder(folderPath));
      }
    }
    return children.values.toList();
  }
}

/**
 * The base class for resources from an [OverlayResourceProvider].
 */
abstract class _OverlayResource implements Resource {
  /**
   * The resource provider associated with this resource.
   */
  final OverlayResourceProvider _provider;

  /**
   * The resource from the provider's base provider that corresponds to this
   * resource.
   */
  final Resource _resource;

  /**
   * Initialize a newly created instance of a resource to have the given
   * [_provider] and to represent the [_resource] from the provider's base
   * resource provider.
   */
  _OverlayResource(this._provider, this._resource);

  /**
   * Return an instance of the subclass of this class corresponding to the given
   * [resource] that is associated with the given [provider].
   */
  factory _OverlayResource._from(
      OverlayResourceProvider provider, Resource resource) {
    if (resource is Folder) {
      return new _OverlayFolder(provider, resource);
    } else if (resource is File) {
      return new _OverlayFile(provider, resource);
    }
    throw new ArgumentError('Unknown resource type: ${resource.runtimeType}');
  }

  @override
  int get hashCode => path.hashCode;

  @override
  Folder get parent {
    Folder parent = _resource.parent;
    if (parent == null) {
      return null;
    }
    return new _OverlayFolder(_provider, parent);
  }

  @override
  String get path => _resource.path;

  @override
  String get shortName => _resource.shortName;

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

  @override
  void delete() {
    _resource.delete();
  }

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

  @override
  Resource resolveSymbolicLinksSync() => new _OverlayResource._from(
      _provider, _resource.resolveSymbolicLinksSync());

  @override
  Uri toUri() => _resource.toUri();
}
