// Copyright (c) 2015, 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.

/// Source information system that maps spans of Dart AST nodes to spans of
/// JavaScript nodes.

library dart2js.source_information.start_end;

import 'package:front_end/src/fasta/scanner.dart' show Token;

import '../common.dart';
import '../diagnostics/messages.dart' show MessageTemplate;
import '../elements/elements.dart'
    show MemberElement, MethodElement, ResolvedAst, ResolvedAstKind;
import '../js/js.dart' as js;
import '../js/js_source_mapping.dart';
import '../tree/tree.dart' show Node, Send;
import '../universe/call_structure.dart';
import 'source_file.dart';
import 'source_information.dart';

/// Source information that contains start source position and optionally an
/// end source position.
class StartEndSourceInformation extends SourceInformation {
  @override
  final SourceLocation startPosition;

  @override
  final SourceLocation endPosition;

  StartEndSourceInformation(this.startPosition, [this.endPosition]);

  @override
  List<SourceLocation> get sourceLocations {
    if (endPosition == null) {
      return <SourceLocation>[startPosition];
    } else {
      return <SourceLocation>[startPosition, endPosition];
    }
  }

  @override
  SourceSpan get sourceSpan {
    Uri uri = startPosition.sourceUri;
    int begin = startPosition.offset;
    int end = endPosition == null ? begin : endPosition.offset;
    return new SourceSpan(uri, begin, end);
  }

  int get hashCode {
    return 0x7FFFFFFF &
        (startPosition.hashCode * 17 + endPosition.hashCode * 19);
  }

  bool operator ==(other) {
    if (identical(this, other)) return true;
    if (other is! StartEndSourceInformation) return false;
    return startPosition == other.startPosition &&
        endPosition == other.endPosition;
  }

  // TODO(johnniwinther): Inline this in
  // [StartEndSourceInformationBuilder.buildDeclaration].
  static StartEndSourceInformation _computeSourceInformation(
      ResolvedAst resolvedAst,
      [CallStructure callStructure]) {
    String name =
        computeElementNameForSourceMaps(resolvedAst.element, callStructure);
    SourceFile sourceFile = computeSourceFile(resolvedAst);
    int begin;
    int end;
    if (resolvedAst.kind != ResolvedAstKind.PARSED) {
      // Synthesized node. Use the enclosing element for the location.
      begin = end = resolvedAst.element.sourcePosition.begin;
    } else {
      Node node = resolvedAst.node;
      begin = node.getBeginToken().charOffset;
      end = node.getEndToken().charOffset;
    }
    // TODO(johnniwinther): find the right sourceFile here and remove offset
    // checks below.
    SourceLocation sourcePosition, endSourcePosition;
    if (begin < sourceFile.length) {
      sourcePosition = new OffsetSourceLocation(sourceFile, begin, name);
    }
    if (end < sourceFile.length) {
      endSourcePosition = new OffsetSourceLocation(sourceFile, end, name);
    }
    return new StartEndSourceInformation(sourcePosition, endSourcePosition);
  }

  /// Create a textual representation of the source information using [uriText]
  /// as the Uri representation.
  String _computeText(String uriText) {
    StringBuffer sb = new StringBuffer();
    sb.write('$uriText:');
    sb.write('[${startPosition.line},${startPosition.column}]');
    if (endPosition != null) {
      sb.write('-[${endPosition.line},${endPosition.column}]');
    }
    return sb.toString();
  }

  String get shortText {
    return _computeText(startPosition.sourceUri.pathSegments.last);
  }

  String toString() {
    return _computeText('${startPosition.sourceUri}');
  }
}

class StartEndSourceInformationStrategy
    extends JavaScriptSourceInformationStrategy<Node> {
  const StartEndSourceInformationStrategy();

  @override
  SourceInformationBuilder<Node> createBuilderForContext(MemberElement member,
      [CallStructure callStructure]) {
    return new StartEndSourceInformationBuilder(member, callStructure);
  }

  @override
  SourceInformationProcessor createProcessor(
      SourceMapperProvider provider, SourceInformationReader reader) {
    return new StartEndSourceInformationProcessor(provider, reader);
  }
}

class StartEndSourceInformationProcessor extends SourceInformationProcessor {
  /// The id for this source information engine.
  ///
  /// The id is added to the source map file in an extra "engine" property and
  /// serves as a version number for the engine.
  ///
  /// The version history of this engine is:
  ///
  ///   v1: The initial version with an id.
  static const String id = 'v1';

  final SourceMapper sourceMapper;
  final SourceInformationReader reader;

  /// Used to track whether a terminating source location marker has been
  /// registered for the top-most node with source information.
  bool hasRegisteredRoot = false;

  /// The root of the tree. Used to add a [NoSourceLocationMarker] to the start
  /// of the output.
  js.Node root;

  /// The root of the current subtree with source information. Used to add
  /// [NoSourceLocationMarker] after areas with source information.
  js.Node subRoot;

  StartEndSourceInformationProcessor(SourceMapperProvider provider, this.reader)
      : this.sourceMapper = provider.createSourceMapper(id);

  void onStartPosition(js.Node node, int startPosition) {
    if (root == null) {
      root = node;
      sourceMapper.register(
          node, startPosition, const NoSourceLocationMarker());
    }
    if (subRoot == null && reader.getSourceInformation(node) != null) {
      subRoot = node;
    }
  }

  @override
  void onPositions(
      js.Node node, int startPosition, int endPosition, int closingPosition) {
    StartEndSourceInformation sourceInformation =
        reader.getSourceInformation(node);
    if (sourceInformation != null) {
      sourceMapper.register(
          node, startPosition, sourceInformation.startPosition);
      if (sourceInformation.endPosition != null) {
        sourceMapper.register(node, endPosition, sourceInformation.endPosition);
      }
      if (!hasRegisteredRoot) {
        sourceMapper.register(node, endPosition, null);
        hasRegisteredRoot = true;
      }
      if (node == subRoot) {
        sourceMapper.register(
            node, endPosition, const NoSourceLocationMarker());
        subRoot = null;
      }
    }
  }
}

/// [SourceInformationBuilder] that generates [PositionSourceInformation].
class StartEndSourceInformationBuilder extends SourceInformationBuilder<Node> {
  final SourceFile sourceFile;
  final String name;

  StartEndSourceInformationBuilder(MemberElement member,
      [CallStructure callStructure])
      : sourceFile = computeSourceFile(member.resolvedAst),
        name = computeElementNameForSourceMaps(
            member.resolvedAst.element, callStructure);

  SourceInformation buildDeclaration(MemberElement member) {
    return StartEndSourceInformation
        ._computeSourceInformation(member.resolvedAst);
  }

  SourceInformation buildStub(
      MethodElement member, CallStructure callStructure) {
    return StartEndSourceInformation._computeSourceInformation(
        member.resolvedAst, callStructure);
  }

  SourceLocation sourceFileLocationForToken(Token token) {
    SourceLocation location =
        new OffsetSourceLocation(sourceFile, token.charOffset, name);
    checkValidSourceFileLocation(location, sourceFile, token.charOffset);
    return location;
  }

  void checkValidSourceFileLocation(
      SourceLocation location, SourceFile sourceFile, int offset) {
    if (!location.isValid) {
      throw MessageTemplate.TEMPLATES[MessageKind.INVALID_SOURCE_FILE_LOCATION]
          .message({
        'offset': offset,
        'fileName': sourceFile.filename,
        'length': sourceFile.length
      });
    }
  }

  @override
  SourceInformation buildLoop(Node node) {
    return new StartEndSourceInformation(
        sourceFileLocationForToken(node.getBeginToken()),
        sourceFileLocationForToken(node.getEndToken()));
  }

  @override
  SourceInformation buildGeneric(Node node) {
    return new StartEndSourceInformation(
        sourceFileLocationForToken(node.getBeginToken()));
  }

  @override
  SourceInformation buildCreate(Node node) => buildGeneric(node);

  @override
  SourceInformation buildReturn(Node node) => buildGeneric(node);

  @override
  SourceInformation buildGet(Node node) => buildGeneric(node);

  @override
  SourceInformation buildAssignment(Node node) => buildGeneric(node);

  @override
  SourceInformation buildCall(Node receiver, Node call) {
    return buildGeneric(receiver);
  }

  @override
  SourceInformation buildAs(Node node) {
    // 'as' is a Send with Operator 'as' for the selector.
    if (node is Send) return buildGeneric(node.selector ?? node);
    return buildGeneric(node);
  }

  @override
  SourceInformation buildIf(Node node) => buildGeneric(node);

  @override
  SourceInformationBuilder forContext(MemberElement member,
      {SourceInformation sourceInformation}) {
    return new StartEndSourceInformationBuilder(member);
  }
}
