// 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() {
    List<Resource> children;
    try {
      children = _folder
          .getChildren()
          .map((child) => new _OverlayResource._from(_provider, child))
          .toList();
    } on FileSystemException {
      children = [];
    }
    for (String overlayPath in _provider._overlaysInFolder(path)) {
      pathos.Context context = _provider.pathContext;
      if (context.dirname(overlayPath) == path) {
        children.add(_provider.getFile(overlayPath));
      } else {
        String relativePath = context.relative(overlayPath, from: path);
        String folderName = context.split(relativePath)[0];
        children.add(_provider.getFolder(context.join(path, folderName)));
      }
    }
    return children;
  }
}

/**
 * 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();
}
