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

import 'package:front_end/src/fasta/builder/qualified_name.dart';
import 'package:front_end/src/fasta/kernel/metadata_collector.dart';
import 'package:front_end/src/incremental/kernel_driver.dart';
import 'package:kernel/kernel.dart' as kernel;

/// Additional information that Analyzer needs for nodes.
class AnalyzerMetadata {
  /// If the node is a named constructor, the offset of the name.
  /// Otherwise `-1`.
  int constructorNameOffset = -1;

  /// Optional documentation comment, may be `null`.
  String documentationComment;

  /// Return the [AnalyzerMetadata] for the [node], or `null` absent.
  static AnalyzerMetadata forNode(kernel.TreeNode node) {
    var repository =
        node.enclosingComponent.metadata[AnalyzerMetadataRepository.TAG];
    if (repository != null) {
      return repository.mapping[node];
    }
    return null;
  }
}

/// Analyzer specific implementation of [MetadataCollector].
class AnalyzerMetadataCollector implements MetadataCollector {
  @override
  final AnalyzerMetadataRepository repository =
      new AnalyzerMetadataRepository();

  @override
  void setConstructorNameOffset(kernel.Member node, Object name) {
    if (name is QualifiedName) {
      var metadata = repository._forWriting(node);
      metadata.constructorNameOffset = name.charOffset;
    }
  }

  @override
  void setDocumentationComment(kernel.NamedNode node, String comment) {
    var metadata = repository._forWriting(node);
    metadata.documentationComment = comment;
  }
}

/// Factory for creating Analyzer specific sink and repository.
class AnalyzerMetadataFactory implements MetadataFactory {
  @override
  int get version => 1;

  @override
  MetadataCollector newCollector() {
    return new AnalyzerMetadataCollector();
  }

  @override
  kernel.MetadataRepository newRepositoryForReading() {
    return new AnalyzerMetadataRepository();
  }
}

/// Analyzer specific implementation of [kernel.MetadataRepository].
class AnalyzerMetadataRepository
    implements kernel.MetadataRepository<AnalyzerMetadata> {
  static const TAG = 'kernel.metadata.analyzer';

  @override
  final String tag = TAG;

  @override
  final Map<kernel.TreeNode, AnalyzerMetadata> mapping =
      <kernel.TreeNode, AnalyzerMetadata>{};

  @override
  AnalyzerMetadata readFromBinary(
      kernel.Node node, kernel.BinarySource source) {
    return new AnalyzerMetadata()
      ..constructorNameOffset = _readOffset(source)
      ..documentationComment = _readOptionalString(source);
  }

  @override
  void writeToBinary(
      AnalyzerMetadata metadata, kernel.Node node, kernel.BinarySink sink) {
    _writeOffset(sink, metadata.constructorNameOffset);
    _writeOptionalString(sink, metadata.documentationComment);
  }

  /// Return the existing or new [AnalyzerMetadata] instance for the [node].
  AnalyzerMetadata _forWriting(kernel.TreeNode node) {
    return mapping[node] ??= new AnalyzerMetadata();
  }

  int _readOffset(kernel.BinarySource source) {
    return source.readUint32() - 1;
  }

  String _readOptionalString(kernel.BinarySource source) {
    int flag = source.readByte();
    if (flag == 1) {
      List<int> bytes = source.readByteList();
      return utf8.decode(bytes);
    } else {
      return null;
    }
  }

  /// The [offset] value must be `>= -1`.
  void _writeOffset(kernel.BinarySink sink, int offset) {
    assert(offset >= -1);
    sink.writeUInt32(1 + offset);
  }

  void _writeOptionalString(kernel.BinarySink sink, String str) {
    if (str != null) {
      sink.writeByte(1);
      List<int> bytes = utf8.encode(str);
      sink.writeByteList(bytes);
    } else {
      sink.writeByte(0);
    }
  }
}
