// Copyright (c) 2017, 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 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/error/error.dart';

import '../analyzer.dart';

const _desc = r'Adhere to Effective Dart Guide directives sorting conventions.';

const _docImportKeyword = '@docImport';

const _exportKeyword = 'export';

const _importKeyword = 'import';

/// Compares directives by package name, then file name in the package.
///
/// The package name is everything until the first '/'.
int compareDirectives(String a, String b) {
  if (!a.startsWith('package:') || !b.startsWith('package:')) {
    if (!a.startsWith('/') && !b.startsWith('/')) {
      return a.compareTo(b);
    }
  }
  var indexA = a.indexOf('/');
  var indexB = b.indexOf('/');
  if (indexA == -1 || indexB == -1) return a.compareTo(b);
  var result = a.substring(0, indexA).compareTo(b.substring(0, indexB));
  if (result != 0) return result;
  return a.substring(indexA + 1).compareTo(b.substring(indexB + 1));
}

bool _isAbsoluteDirective(NamespaceDirective node) {
  var uriContent = node.uri.stringValue;
  return uriContent != null && uriContent.contains(':');
}

bool _isDartDirective(NamespaceDirective node) {
  var uriContent = node.uri.stringValue;
  return uriContent != null && uriContent.startsWith('dart:');
}

bool _isExportDirective(Directive node) => node is ExportDirective;

bool _isNotDartDirective(NamespaceDirective node) => !_isDartDirective(node);

bool _isPackageDirective(NamespaceDirective node) {
  var uriContent = node.uri.stringValue;
  return uriContent != null && uriContent.startsWith('package:');
}

bool _isPartDirective(Directive node) => node is PartDirective;

bool _isRelativeDirective(NamespaceDirective node) =>
    !_isAbsoluteDirective(node);

class DirectivesOrdering extends MultiAnalysisRule {
  static const List<LintCode> allCodes = [
    LinterLintCode.directives_ordering_alphabetical,
    LinterLintCode.directives_ordering_dart,
    LinterLintCode.directives_ordering_exports,
    LinterLintCode.directives_ordering_package_before_relative,
  ];

  DirectivesOrdering()
    : super(name: LintNames.directives_ordering, description: _desc);

  @override
  List<DiagnosticCode> get diagnosticCodes => allCodes;

  @override
  void registerNodeProcessors(
    NodeLintRegistry registry,
    LinterContext context,
  ) {
    var visitor = _Visitor(this);
    registry.addCompilationUnit(this, visitor);
  }

  void _reportLintWithDartDirectiveGoFirstMessage(AstNode node, String type) {
    reportAtNode(
      node,
      diagnosticCode: LinterLintCode.directives_ordering_dart,
      arguments: [type],
    );
  }

  void _reportLintWithDirectiveSectionOrderedAlphabeticallyMessage(
    AstNode node,
  ) {
    reportAtNode(
      node,
      diagnosticCode: LinterLintCode.directives_ordering_alphabetical,
    );
  }

  void _reportLintWithExportDirectiveAfterImportDirectiveMessage(AstNode node) {
    reportAtNode(
      node,
      diagnosticCode: LinterLintCode.directives_ordering_exports,
    );
  }

  void _reportLintWithPackageDirectiveBeforeRelativeMessage(
    AstNode node,
    String type,
  ) {
    reportAtNode(
      node,
      diagnosticCode:
          LinterLintCode.directives_ordering_package_before_relative,
      arguments: [type],
    );
  }
}

class _Visitor extends SimpleAstVisitor<void> {
  final DirectivesOrdering rule;

  _Visitor(this.rule);

  @override
  void visitCompilationUnit(CompilationUnit node) {
    var lintedNodes = <AstNode>{};
    _checkDartDirectiveGoFirst(lintedNodes, node);
    _checkPackageDirectiveBeforeRelative(lintedNodes, node);
    _checkExportDirectiveAfterImportDirective(lintedNodes, node);
    _checkDirectiveSectionOrderedAlphabetically(lintedNodes, node);
  }

  void _checkDartDirectiveGoFirst(
    Set<AstNode> lintedNodes,
    CompilationUnit node,
  ) {
    for (var import in node.importDirectives.withDartUrisSkippingTheFirstSet) {
      if (lintedNodes.add(import)) {
        rule._reportLintWithDartDirectiveGoFirstMessage(import, _importKeyword);
      }
    }

    for (var export in node.exportDirectives.withDartUrisSkippingTheFirstSet) {
      if (lintedNodes.add(export)) {
        rule._reportLintWithDartDirectiveGoFirstMessage(export, _exportKeyword);
      }
    }

    for (var import
        in node.docImportDirectives.withDartUrisSkippingTheFirstSet) {
      if (lintedNodes.add(import)) {
        rule._reportLintWithDartDirectiveGoFirstMessage(
          import,
          _docImportKeyword,
        );
      }
    }
  }

  void _checkDirectiveSectionOrderedAlphabetically(
    Set<AstNode> lintedNodes,
    CompilationUnit node,
  ) {
    var dartImports = node.importDirectives.where(_isDartDirective);
    var dartExports = node.exportDirectives.where(_isDartDirective);
    var dartDocImports = node.docImportDirectives.where(_isDartDirective);

    _checkSectionInOrder(lintedNodes, dartImports);
    _checkSectionInOrder(lintedNodes, dartExports);
    _checkSectionInOrder(lintedNodes, dartDocImports);

    var relativeImports = node.importDirectives.where(_isRelativeDirective);
    var relativeExports = node.exportDirectives.where(_isRelativeDirective);
    var relativeDocImports = node.docImportDirectives.where(
      _isRelativeDirective,
    );

    _checkSectionInOrder(lintedNodes, relativeImports);
    _checkSectionInOrder(lintedNodes, relativeExports);
    _checkSectionInOrder(lintedNodes, relativeDocImports);

    // See: https://github.com/dart-lang/linter/issues/3395
    // (`DartProject` removal)
    // The rub is that *all* projects are being treated as "not pub"
    // packages.  We'll want to be careful when fixing this since it
    // will have ecosystem impact.

    // Not a pub package. Package directives should be sorted in one block.
    var packageImports = node.importDirectives.where(_isPackageDirective);
    var packageExports = node.exportDirectives.where(_isPackageDirective);
    var packageDocImports = node.docImportDirectives.where(_isPackageDirective);

    _checkSectionInOrder(lintedNodes, packageImports);
    _checkSectionInOrder(lintedNodes, packageExports);
    _checkSectionInOrder(lintedNodes, packageDocImports);

    // The following is relying on projectName which is meant to come from
    // a `DartProject` instance (but was not since the project was always null)
    // else {
    //   var packageBox = _PackageBox(projectName);
    //
    //   var thirdPartyPackageImports =
    //       importDirectives.where(packageBox._isNotOwnPackageDirective);
    //   var thirdPartyPackageExports =
    //       exportDirectives.where(packageBox._isNotOwnPackageDirective);
    //
    //   var ownPackageImports =
    //       importDirectives.where(packageBox._isOwnPackageDirective);
    //   var ownPackageExports =
    //       exportDirectives.where(packageBox._isOwnPackageDirective);
    //
    //   _checkSectionInOrder(lintedNodes, thirdPartyPackageImports);
    //   _checkSectionInOrder(lintedNodes, thirdPartyPackageExports);
    //
    //   _checkSectionInOrder(lintedNodes, ownPackageImports);
    //   _checkSectionInOrder(lintedNodes, ownPackageExports);
    // }
  }

  void _checkExportDirectiveAfterImportDirective(
    Set<AstNode> lintedNodes,
    CompilationUnit node,
  ) {
    for (var directive in node.directives.reversed
        .skipWhile(_isPartDirective)
        .skipWhile(_isExportDirective)
        .where(_isExportDirective)) {
      if (lintedNodes.add(directive)) {
        rule._reportLintWithExportDirectiveAfterImportDirectiveMessage(
          directive,
        );
      }
    }
  }

  void _checkPackageDirectiveBeforeRelative(
    Set<AstNode> lintedNodes,
    CompilationUnit node,
  ) {
    for (var import
        in node.importDirectives.withPackageUrisSkippingAbsoluteUris) {
      if (lintedNodes.add(import)) {
        rule._reportLintWithPackageDirectiveBeforeRelativeMessage(
          import,
          _importKeyword,
        );
      }
    }

    for (var export
        in node.exportDirectives.withPackageUrisSkippingAbsoluteUris) {
      if (lintedNodes.add(export)) {
        rule._reportLintWithPackageDirectiveBeforeRelativeMessage(
          export,
          _exportKeyword,
        );
      }
    }

    for (var import
        in node.docImportDirectives.withPackageUrisSkippingAbsoluteUris) {
      if (lintedNodes.add(import)) {
        rule._reportLintWithPackageDirectiveBeforeRelativeMessage(
          import,
          _docImportKeyword,
        );
      }
    }
  }

  void _checkSectionInOrder(
    Set<AstNode> lintedNodes,
    Iterable<UriBasedDirective> nodes,
  ) {
    if (nodes.isEmpty) return;

    var previousUri = nodes.first.uri.stringValue;
    for (var directive in nodes.skip(1)) {
      var directiveUri = directive.uri.stringValue;
      if (previousUri != null &&
          directiveUri != null &&
          compareDirectives(previousUri, directiveUri) > 0) {
        if (lintedNodes.add(directive)) {
          rule._reportLintWithDirectiveSectionOrderedAlphabeticallyMessage(
            directive,
          );
        }
      }
      previousUri = directive.uri.stringValue;
    }
  }
}

extension on CompilationUnit {
  Iterable<ImportDirective> get docImportDirectives {
    var libraryDirective = directives.whereType<LibraryDirective>().firstOrNull;
    if (libraryDirective == null) return const [];
    var docComment = libraryDirective.documentationComment;
    if (docComment == null) return const [];
    return docComment.docImports.map((e) => e.import);
  }

  Iterable<ExportDirective> get exportDirectives =>
      directives.whereType<ExportDirective>();

  Iterable<ImportDirective> get importDirectives =>
      directives.whereType<ImportDirective>();
}

extension on Iterable<NamespaceDirective> {
  /// The directives with 'dart:' URIs, skipping the first such set of
  /// directives.
  Iterable<NamespaceDirective> get withDartUrisSkippingTheFirstSet =>
      skipWhile(_isDartDirective).where(_isDartDirective);

  /// The directives with 'package:' URIs, after the first set of directives
  /// with absolute URIs.
  Iterable<NamespaceDirective> get withPackageUrisSkippingAbsoluteUris => where(
    _isNotDartDirective,
  ).skipWhile(_isAbsoluteDirective).where(_isPackageDirective);
}
