// 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/analyzer.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:linter/src/analyzer.dart';

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

**DO** follow the conventions in the 
[Effective Dart Guide](https://www.dartlang.org/guides/language/effective-dart/style#ordering)

**DO** place “dart:” imports before other imports.

**BAD:**
```
import 'package:bar/bar.dart';
import 'package:foo/foo.dart';

import 'dart:async';  // LINT
import 'dart:html';  // LINT
```

**BAD:**
```
import 'dart:html';  // OK
import 'package:bar/bar.dart';

import 'dart:async';  // LINT
import 'package:foo/foo.dart';
```

**GOOD:**
```
import 'dart:async';  // OK
import 'dart:html';  // OK

import 'package:bar/bar.dart';
import 'package:foo/foo.dart';
```

**DO** place “package:” imports before relative imports.

**BAD:**
```
import 'a.dart';
import 'b.dart';

import 'package:bar/bar.dart';  // LINT
import 'package:foo/foo.dart';  // LINT
```
**BAD:**
```
import 'package:bar/bar.dart';  // OK
import 'a.dart';

import 'package:foo/foo.dart';  // LINT
import 'b.dart';
```

**GOOD:**
```
import 'package:bar/bar.dart';  // OK
import 'package:foo/foo.dart';  // OK

import 'a.dart';
import 'b.dart';
```

**PREFER** placing “third-party” “package:” imports before other imports.

**BAD:**
```
import 'package:myapp/io.dart';
import 'package:myapp/util.dart';

import 'package:bar/bar.dart';  // LINT
import 'package:foo/foo.dart';  // LINT
```

**GOOD:**
```
import 'package:bar/bar.dart';  // OK
import 'package:foo/foo.dart';  // OK

import 'package:myapp/io.dart';
import 'package:myapp/util.dart';
```

**DO** specify exports in a separate section after all imports.

**BAD:**
```
import 'src/error.dart';
export 'src/error.dart'; // LINT
import 'src/string_source.dart';
```

**GOOD:**
```
import 'src/error.dart';
import 'src/string_source.dart';

export 'src/error.dart'; // OK
```

**DO** sort sections alphabetically.

**BAD:**
```
import 'package:foo/bar.dart'; // OK
import 'package:bar/bar.dart'; // LINT

import 'a/b.dart'; // OK
import 'a.dart'; // LINT
```

**GOOD:**
```
import 'package:bar/bar.dart'; // OK
import 'package:foo/bar.dart'; // OK

import 'a.dart'; // OK
import 'a/b.dart'; // OK

''';
const _importKeyword = 'import';

const _exportKeyword = 'export';

const _directiveSectionOrderedAlphabetically =
    'Sort directive sections alphabetically.';

const _exportDirectiveAfterImportDirectives =
    'Specify exports in a separate section after all imports.';

String _dartDirectiveGoFirst(String type) =>
    "Place 'dart:' ${type}s before other ${type}s.";

bool _isAbsoluteDirective(NamespaceDirective node) =>
    node.uriContent.contains(':');

bool _isDartDirective(NamespaceDirective node) =>
    node.uriContent.startsWith('dart:');

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

bool _isImportDirective(Directive node) => node is ImportDirective;

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

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

bool _isPackageDirective(NamespaceDirective node) =>
    node.uriContent.startsWith('package:');

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

String _packageDirectiveBeforeRelative(String type) =>
    "Place 'package:' ${type}s before relative ${type}s.";

String _thirdPartyPackageDirectiveBeforeOwn(String type) =>
    "Place 'third-party' 'package:' ${type}s before other ${type}s.";

class DirectivesOrdering extends LintRule implements ProjectVisitor {
  _Visitor _visitor;
  DartProject project;

  DirectivesOrdering()
      : super(
            name: 'directives_ordering',
            description: _desc,
            details: _details,
            group: Group.style) {
    _visitor = new _Visitor(this);
  }

  @override
  ProjectVisitor getProjectVisitor() => this;

  @override
  AstVisitor getVisitor() => _visitor;

  @override
  visit(DartProject project) {
    this.project = project;
  }

  void _reportLintWithDartDirectiveGoFirstMessage(AstNode node, String type) {
    _reportLintWithDescription(node, _dartDirectiveGoFirst(type));
  }

  void _reportLintWithDescription(AstNode node, String description) {
    reporter.reportErrorForNode(new LintCode(name, description), node, []);
  }

  void _reportLintWithDirectiveSectionOrderedAlphabeticallyMessage(
      AstNode node) {
    _reportLintWithDescription(node, _directiveSectionOrderedAlphabetically);
  }

  void _reportLintWithExportDirectiveAfterImportDirectiveMessage(AstNode node) {
    _reportLintWithDescription(node, _exportDirectiveAfterImportDirectives);
  }

  void _reportLintWithPackageDirectiveBeforeRelativeMessage(
      AstNode node, String type) {
    _reportLintWithDescription(node, _packageDirectiveBeforeRelative(type));
  }

  void _reportLintWithThirdPartyPackageDirectiveBeforeOwnMessage(
      AstNode node, String type) {
    _reportLintWithDescription(
        node, _thirdPartyPackageDirectiveBeforeOwn(type));
  }
}

class _PackageBox {
  final String _packageName;
  _PackageBox(this._packageName);

  bool _isNotOwnPackageDirective(NamespaceDirective node) =>
      _isPackageDirective(node) && !_isOwnPackageDirective(node);

  bool _isOwnPackageDirective(NamespaceDirective node) =>
      node.uriContent.startsWith('package:$_packageName/');
}

class _Visitor extends SimpleAstVisitor {
  final DirectivesOrdering rule;

  _Visitor(this.rule);

  DartProject get project => rule.project;

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

  void _checkDartDirectiveGoFirst(
      Set<AstNode> lintedNodes, CompilationUnit node) {
    void reportImport(NamespaceDirective directive) {
      if (lintedNodes.add(directive)) {
        rule._reportLintWithDartDirectiveGoFirstMessage(
            directive, _importKeyword);
      }
    }

    void reportExport(NamespaceDirective directive) {
      if (lintedNodes.add(directive)) {
        rule._reportLintWithDartDirectiveGoFirstMessage(
            directive, _exportKeyword);
      }
    }

    Iterable<NamespaceDirective> getNodesToLint(
            Iterable<NamespaceDirective> directives) =>
        directives.skipWhile(_isDartDirective).where(_isDartDirective);

    getNodesToLint(_getImportDirectives(node)).forEach(reportImport);

    getNodesToLint(_getExportDirectives(node)).forEach(reportExport);
  }

  void _checkDirectiveSectionOrderedAlphabetically(
      Set<AstNode> lintedNodes, CompilationUnit node) {
    final importDirectives = _getImportDirectives(node);
    final exportDirectives = _getExportDirectives(node);

    final dartImports = importDirectives.where(_isDartDirective);
    final dartExports = exportDirectives.where(_isDartDirective);

    final relativeImports = importDirectives.where(_isRelativeDirective);
    final relativeExports = exportDirectives.where(_isRelativeDirective);

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

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

    if (project != null) {
      _PackageBox packageBox = new _PackageBox(project.name);

      final thirdPartyPackageImports =
          importDirectives.where(packageBox._isNotOwnPackageDirective);
      final thirdPartyPackageExports =
          exportDirectives.where(packageBox._isNotOwnPackageDirective);

      final ownPackageImports =
          importDirectives.where(packageBox._isOwnPackageDirective);
      final ownPackageExports =
          exportDirectives.where(packageBox._isOwnPackageDirective);

      _checkSectionInOrder(lintedNodes, thirdPartyPackageImports);
      _checkSectionInOrder(lintedNodes, thirdPartyPackageExports);

      _checkSectionInOrder(lintedNodes, ownPackageImports);
      _checkSectionInOrder(lintedNodes, ownPackageExports);
    }
  }

  void _checkExportDirectiveAfterImportDirective(
      Set<AstNode> lintedNodes, CompilationUnit node) {
    void reportDirective(Directive directive) {
      if (lintedNodes.add(directive)) {
        rule._reportLintWithExportDirectiveAfterImportDirectiveMessage(
            directive);
      }
    }

    node.directives.reversed
        .skipWhile(_isPartDirective)
        .skipWhile(_isExportDirective)
        .where(_isExportDirective)
        .forEach(reportDirective);
  }

  void _checkPackageDirectiveBeforeRelative(
      Set<AstNode> lintedNodes, CompilationUnit node) {
    void reportImport(NamespaceDirective directive) {
      if (lintedNodes.add(directive)) {
        rule._reportLintWithPackageDirectiveBeforeRelativeMessage(
            directive, _importKeyword);
      }
    }

    void reportExport(NamespaceDirective directive) {
      if (lintedNodes.add(directive)) {
        rule._reportLintWithPackageDirectiveBeforeRelativeMessage(
            directive, _exportKeyword);
      }
    }

    Iterable<NamespaceDirective> getNodesToLint(
            Iterable<NamespaceDirective> directives) =>
        directives
            .where(_isNotDartDirective)
            .skipWhile(_isAbsoluteDirective)
            .where(_isPackageDirective);

    getNodesToLint(_getImportDirectives(node)).forEach(reportImport);

    getNodesToLint(_getExportDirectives(node)).forEach(reportExport);
  }

  void _checkSectionInOrder(
      Set<AstNode> lintedNodes, Iterable<NamespaceDirective> nodes) {
    void reportDirective(NamespaceDirective directive) {
      if (lintedNodes.add(directive)) {
        rule._reportLintWithDirectiveSectionOrderedAlphabeticallyMessage(
            directive);
      }
    }

    NamespaceDirective previousDirective;
    for (NamespaceDirective directive in nodes) {
      if (previousDirective != null &&
          previousDirective.uriContent.compareTo(directive.uriContent) > 0) {
        reportDirective(directive);
      }
      previousDirective = directive;
    }
  }

  void _checkThirdPartyDirectiveBeforeOwn(
      Set<AstNode> lintedNodes, CompilationUnit node) {
    if (project == null) {
      return;
    }

    void reportImport(NamespaceDirective directive) {
      if (lintedNodes.add(directive)) {
        rule._reportLintWithThirdPartyPackageDirectiveBeforeOwnMessage(
            directive, _importKeyword);
      }
    }

    void reportExport(NamespaceDirective directive) {
      if (lintedNodes.add(directive)) {
        rule._reportLintWithThirdPartyPackageDirectiveBeforeOwnMessage(
            directive, _exportKeyword);
      }
    }

    Iterable<NamespaceDirective> getNodesToLint(
        Iterable<NamespaceDirective> directives) {
      _PackageBox box = new _PackageBox(project.name);
      return directives
          .where(_isPackageDirective)
          .skipWhile(box._isNotOwnPackageDirective)
          .where(box._isNotOwnPackageDirective);
    }

    getNodesToLint(_getImportDirectives(node)).forEach(reportImport);

    getNodesToLint(_getExportDirectives(node)).forEach(reportExport);
  }

  Iterable<ExportDirective> _getExportDirectives(CompilationUnit node) =>
      node.directives
          .where(_isExportDirective)
          .map((e) => e as ExportDirective);

  Iterable<ImportDirective> _getImportDirectives(CompilationUnit node) =>
      node.directives
          .where(_isImportDirective)
          .map((e) => e as ImportDirective);
}
