// 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:core';

import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:path/path.dart' show posix;

/// A contributor that produces suggestions based on the content of the file
/// system to complete within URIs in import, export and part directives.
class UriContributor extends DartCompletionContributor {
  /// A flag indicating whether file: and package: URI suggestions should
  /// be included in the list of completion suggestions.
  // TODO(danrubel): remove this flag and related functionality
  // once the UriContributor limits file: and package: URI suggestions
  // to only those paths within context roots.
  static bool suggestFilePaths = true;

  @override
  Future<void> computeSuggestions(
      DartCompletionRequest request, SuggestionBuilder builder) async {
    var visitor = _UriSuggestionBuilder(request, builder);
    request.target.containingNode.accept(visitor);
  }
}

class _UriSuggestionBuilder extends SimpleAstVisitor<void> {
  final DartCompletionRequest request;

  final SuggestionBuilder builder;

  _UriSuggestionBuilder(this.request, this.builder);

  @override
  void visitExportDirective(ExportDirective node) {
    visitNamespaceDirective(node);
  }

  @override
  void visitImportDirective(ImportDirective node) {
    visitNamespaceDirective(node);
  }

  void visitNamespaceDirective(NamespaceDirective node) {
    var uri = node.uri;
    if (uri is SimpleStringLiteral) {
      var offset = request.offset;
      var start = uri.offset;
      var end = uri.end;
      if (offset > start) {
        if (offset < end) {
          // Quoted non-empty string
          visitSimpleStringLiteral(uri);
        } else if (offset == end) {
          if (end == start + 1) {
            // Quoted empty string
            visitSimpleStringLiteral(uri);
          } else {
            var data = request.sourceContents;
            if (end == data.length) {
              var ch = data[end - 1];
              if (ch != '"' && ch != "'") {
                // Insertion point at end of file
                // and missing closing quote on non-empty string
                visitSimpleStringLiteral(uri);
              }
            }
          }
        }
      } else if (offset == start && offset == end) {
        var data = request.sourceContents;
        if (end == data.length) {
          var ch = data[end - 1];
          if (ch == '"' || ch == "'") {
            // Insertion point at end of file
            // and missing closing quote on empty string
            visitSimpleStringLiteral(uri);
          }
        }
      }
    }
  }

  @override
  void visitSimpleStringLiteral(SimpleStringLiteral node) {
    var parent = node.parent;
    if (parent is NamespaceDirective && parent.uri == node) {
      var partialUri = _extractPartialUri(node);
      if (partialUri != null) {
        _addDartSuggestions();
        if (UriContributor.suggestFilePaths) {
          _addPackageSuggestions(partialUri);
          _addFileSuggestions(partialUri);
        }
      }
    } else if (parent is PartDirective && parent.uri == node) {
      var partialUri = _extractPartialUri(node);
      if (partialUri != null) {
        if (UriContributor.suggestFilePaths) {
          _addFileSuggestions(partialUri);
        }
      }
    }
  }

  void _addDartSuggestions() {
    builder.suggestUri('dart:');
    var factory = request.sourceFactory;
    for (var lib in factory.dartSdk.sdkLibraries) {
      if (!lib.isInternal && !lib.isImplementation) {
        if (!lib.shortName.startsWith('dart:_')) {
          builder.suggestUri(lib.shortName);
        }
      }
    }
  }

  void _addFileSuggestions(String partialUri) {
    var resProvider = request.resourceProvider;
    var resContext = resProvider.pathContext;
    var source = request.source;

    String parentUri;
    if ((partialUri.endsWith('/'))) {
      parentUri = partialUri;
    } else {
      parentUri = posix.dirname(partialUri);
      if (parentUri != '.' && !parentUri.endsWith('/')) {
        parentUri = '$parentUri/';
      }
    }
    var uriPrefix = parentUri == '.' ? '' : parentUri;

    // Only handle file uris in the format file:///xxx or /xxx
    var parentUriScheme = Uri.parse(parentUri).scheme;
    if (!parentUri.startsWith('file://') && parentUriScheme != '') {
      return;
    }

    var dirPath = resProvider.pathContext.fromUri(parentUri);
    dirPath = resContext.normalize(dirPath);

    if (resContext.isRelative(dirPath)) {
      var sourceDirPath = resContext.dirname(source.fullName);
      if (resContext.isAbsolute(sourceDirPath)) {
        dirPath = resContext.normalize(resContext.join(sourceDirPath, dirPath));
      } else {
        return;
      }
      // Do not suggest relative paths reaching outside the 'lib' directory.
      var srcInLib = resContext.split(sourceDirPath).contains('lib');
      var dstInLib = resContext.split(dirPath).contains('lib');
      if (srcInLib && !dstInLib) {
        return;
      }
    }
    if (dirPath.endsWith('\\.')) {
      dirPath = dirPath.substring(0, dirPath.length - 1);
    }

    var dir = resProvider.getResource(dirPath);
    if (dir is Folder) {
      try {
        for (var child in dir.getChildren()) {
          String completion;
          if (child is Folder) {
            if (!child.shortName.startsWith('.')) {
              completion = '$uriPrefix${child.shortName}/';
            }
          } else if (child is File) {
            if (child.shortName.endsWith('.dart')) {
              completion = '$uriPrefix${child.shortName}';
            }
          }
          if (completion != null && completion != source.shortName) {
            builder.suggestUri(completion);
          }
        }
      } on FileSystemException {
        // Guard against I/O exceptions.
      }
    }
  }

  void _addPackageFolderSuggestions(
      String partial, String prefix, Folder folder) {
    try {
      for (var child in folder.getChildren()) {
        if (child is Folder) {
          var childPrefix = '$prefix${child.shortName}/';
          builder.suggestUri(childPrefix);
          if (partial.startsWith(childPrefix)) {
            _addPackageFolderSuggestions(partial, childPrefix, child);
          }
        } else {
          builder.suggestUri('$prefix${child.shortName}');
        }
      }
    } on FileSystemException {
      // Guard against I/O exceptions.
      return;
    }
  }

  void _addPackageSuggestions(String partial) {
    var factory = request.sourceFactory;
    var packageMap = factory.packageMap;
    if (packageMap != null) {
      builder.suggestUri('package:');
      packageMap.forEach((pkgName, folders) {
        var prefix = 'package:$pkgName/';
        builder.suggestUri(prefix);
        for (var folder in folders) {
          if (folder.exists) {
            _addPackageFolderSuggestions(partial, prefix, folder);
          }
        }
      });
    }
  }

  String _extractPartialUri(SimpleStringLiteral node) {
    if (request.offset < node.contentsOffset) {
      return null;
    }
    return node.literal.lexeme.substring(
        node.contentsOffset - node.offset, request.offset - node.offset);
  }
}
