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

/// Listener used in combination with `TopLevelParser` to extract the URIs of
/// import, part, and export directives.
library front_end.src.fasta.source.directive_listener;

import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
import 'package:_fe_analyzer_shared/src/parser/identifier_context.dart';
import 'package:_fe_analyzer_shared/src/parser/listener.dart';
import 'package:_fe_analyzer_shared/src/parser/quote.dart';
import '../fasta_codes.dart' show messageExpectedBlockToSkip;

/// Listener that records imports, exports, and part directives.
///
/// This is normally used in combination with the `TopLevelParser`, which skips
/// over the body of declarations like classes and function that are irrelevant
/// for directives. Note that on correct programs directives cannot occur after
/// any top-level declaration, but we recommend to continue parsing the entire
/// file in order to gracefully handle input errors.
class DirectiveListener extends Listener {
  /// Import directives with URIs and combinators.
  final List<NamespaceDirective> imports = <NamespaceDirective>[];

  /// Export directives with URIs and combinators.
  final List<NamespaceDirective> exports = <NamespaceDirective>[];

  /// Collects URIs that occur on any part directive.
  final Set<String> parts = new Set<String>();

  bool _inPart = false;
  String _uri;
  List<NamespaceCombinator> _combinators;
  List<String> _combinatorNames;

  DirectiveListener();

  @override
  beginExport(Token export) {
    _combinators = <NamespaceCombinator>[];
  }

  @override
  void beginHide(Token hide) {
    _combinatorNames = <String>[];
  }

  @override
  beginImport(Token import) {
    _combinators = <NamespaceCombinator>[];
  }

  @override
  void beginLiteralString(Token token) {
    if (_combinators != null || _inPart) {
      _uri = unescapeString(token.lexeme, token, this);
    }
  }

  @override
  beginPart(Token part) {
    _inPart = true;
  }

  @override
  void beginShow(Token show) {
    _combinatorNames = <String>[];
  }

  @override
  endExport(Token export, Token semicolon) {
    exports.add(new NamespaceDirective.export(_uri, _combinators));
    _uri = null;
    _combinators = null;
  }

  @override
  void endHide(Token hide) {
    _combinators.add(new NamespaceCombinator.hide(_combinatorNames));
    _combinatorNames = null;
  }

  @override
  endImport(Token import, Token semicolon) {
    imports.add(new NamespaceDirective.import(_uri, _combinators));
    _uri = null;
    _combinators = null;
  }

  @override
  endPart(Token part, Token semicolon) {
    parts.add(_uri);
    _uri = null;
    _inPart = false;
  }

  @override
  void endShow(Token show) {
    _combinators.add(new NamespaceCombinator.show(_combinatorNames));
    _combinatorNames = null;
  }

  @override
  void handleIdentifier(Token token, IdentifierContext context) {
    if (_combinatorNames != null && context == IdentifierContext.combinator) {
      _combinatorNames.add(token.lexeme);
    }
  }

  /// By default, native clauses are not handled and an error is thrown.
  @override
  void handleNativeFunctionBodySkipped(Token nativeToken, Token semicolon) {
    super.handleRecoverableError(
        messageExpectedBlockToSkip, nativeToken, nativeToken);
  }
}

class NamespaceCombinator {
  final bool isShow;
  final Set<String> names;

  NamespaceCombinator.hide(List<String> names)
      : isShow = false,
        names = names.toSet();

  NamespaceCombinator.show(List<String> names)
      : isShow = true,
        names = names.toSet();
}

class NamespaceDirective {
  final bool isImport;
  final String uri;
  final List<NamespaceCombinator> combinators;

  NamespaceDirective.export(this.uri, this.combinators) : isImport = false;

  NamespaceDirective.import(this.uri, this.combinators) : isImport = true;
}
