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

library context.directory.manager;

import 'dart:async';

import 'package:analysis_server/src/resource.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:watcher/watcher.dart';

/**
 * Information tracked by the [ContextDirectoryManager] for each context.
 */
class _ContextDirectoryInfo {
  /**
   * Stream subscription we are using to watch the context's directory for
   * changes.
   */
  StreamSubscription<WatchEvent> changeSubscription;

  /**
   * Map from full path to the [Source] object, for each source that has been
   * added to the context.
   */
  Map<String, Source> sources = <String, Source>{};
}

/**
 * Class that maintains a mapping from included/excluded paths to a set of
 * folders that should correspond to analysis contexts.
 */
abstract class ContextDirectoryManager {
  /**
   * [_ContextDirectoryInfo] object for each included directory in the most
   * recent successful call to [setRoots].
   */
  Map<Folder, _ContextDirectoryInfo> _currentDirectoryInfo =
      <Folder, _ContextDirectoryInfo>{};

  /**
   * The [ResourceProvider] using which paths are converted into [Resource]s.
   */
  final ResourceProvider resourceProvider;

  ContextDirectoryManager(this.resourceProvider);

  /**
   * Change the set of paths which should be used as starting points to
   * determine the context directories.
   */
  void setRoots(List<String> includedPaths,
                List<String> excludedPaths) {
    // included
    Set<Folder> includedFolders = new Set<Folder>();
    for (int i = 0; i < includedPaths.length; i++) {
      String path = includedPaths[i];
      Resource resource = resourceProvider.getResource(path);
      if (resource is Folder) {
        includedFolders.add(resource);
      } else {
        // TODO(scheglov) implemented separate files analysis
        throw new UnimplementedError(
            '$path is not a folder. '
            'Only support for folder analysis is implemented currently.');
      }
    }
    // excluded
    // TODO(scheglov) remove when implemented
    if (excludedPaths.isNotEmpty) {
      throw new UnimplementedError(
          'Excluded paths are not supported yet');
    }
    Set<Folder> excludedFolders = new Set<Folder>();
    // diff
    Set<Folder> currentFolders = _currentDirectoryInfo.keys.toSet();
    Set<Folder> newFolders = includedFolders.difference(currentFolders);
    Set<Folder> oldFolders = currentFolders.difference(includedFolders);
    // remove old contexts
    for (Folder folder in oldFolders) {
      // TODO(scheglov) implement
    }
    // add new contexts
    for (Folder folder in newFolders) {
      _ContextDirectoryInfo info = new _ContextDirectoryInfo();
      _currentDirectoryInfo[folder] = info;
      info.changeSubscription = folder.changes.listen((WatchEvent event) {
        _handleWatchEvent(folder, info, event);
      });
      File pubspecFile = folder.getChild('pubspec.yaml');
      addContext(folder, pubspecFile.exists ? pubspecFile : null);
      ChangeSet changeSet = new ChangeSet();
      _addSourceFiles(changeSet, folder, info);
      applyChangesToContext(folder, changeSet);
    }
  }

  void _handleWatchEvent(Folder folder, _ContextDirectoryInfo info, WatchEvent event) {
    switch (event.type) {
      case ChangeType.ADD:
        if (_isInPackagesDir(event.path, folder)) {
          // TODO(paulberry): perhaps we should only skip packages dirs if
          // there is a pubspec.yaml?
          break;
        }
        // TODO(paulberry): handle adding pubspec.yaml
        if (_shouldFileBeAnalyzed(event.path)) {
          ChangeSet changeSet = new ChangeSet();
          Resource resource = resourceProvider.getResource(event.path);
          // If the file went away and was replaced by a folder before we
          // had a chance to process the event, resource might be a Folder.  In
          // that case don't add it.
          if (resource is File) {
            File file = resource;
            Source source = file.createSource(UriKind.FILE_URI);
            changeSet.addedSource(source);
            applyChangesToContext(folder, changeSet);
            info.sources[event.path]= source;
          }
        }
        break;
      case ChangeType.REMOVE:
        // TODO(paulberry): handle removing pubspec.yaml
        Source source = info.sources[event.path];
        if (source != null) {
          ChangeSet changeSet = new ChangeSet();
          changeSet.removedSource(source);
          applyChangesToContext(folder, changeSet);
          info.sources.remove(event.path);
        }
        break;
      case ChangeType.MODIFY:
        // TODO(paulberry): handle modification events
        break;
    }
  }

  /**
   * Determine if the path from [folder] to [path] contains a 'packages'
   * directory.
   */
  bool _isInPackagesDir(String path, Folder folder) {
    String relativePath = resourceProvider.pathContext.relative(path, from: folder.path);
    List<String> pathParts = resourceProvider.pathContext.split(relativePath);
    for (int i = 0; i < pathParts.length - 1; i++) {
      if (pathParts[i] == 'packages') {
        return true;
      }
    }
    return false;
  }

  /**
   * Resursively adds all Dart and HTML files to the [changeSet].
   */
  static void _addSourceFiles(ChangeSet changeSet, Folder folder, _ContextDirectoryInfo info) {
    List<Resource> children = folder.getChildren();
    for (Resource child in children) {
      if (child is File) {
        if (_shouldFileBeAnalyzed(child.path)) {
          Source source = child.createSource(UriKind.FILE_URI);
          changeSet.addedSource(source);
          info.sources[child.path] = source;
        }
      } else if (child is Folder) {
        if (child.shortName == 'packages') {
          // TODO(paulberry): perhaps we should only skip packages dirs if
          // there is a pubspec.yaml?
          continue;
        }
        _addSourceFiles(changeSet, child, info);
      }
    }
  }

  static bool _shouldFileBeAnalyzed(String path) {
    return AnalysisEngine.isDartFileName(path)
            || AnalysisEngine.isHtmlFileName(path);
  }

  /**
   * Called when a new context needs to be created.  If the context is
   * associated with a pubspec file, that file is passed in [pubspecFile];
   * otherwise it is null.
   */
  void addContext(Folder folder, File pubspecFile);

  /**
   * Called when the set of files associated with a context have changed (or
   * some of those files have been modified).  [changeSet] is the set of
   * changes that need to be applied to the context.
   */
  void applyChangesToContext(Folder contextFolder, ChangeSet changeSet);
}