// 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.enclosingProgram.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.BinarySource source) {
    return new AnalyzerMetadata()
      ..constructorNameOffset = _readOffset(source)
      ..documentationComment = _readOptionalString(source);
  }

  @override
  void writeToBinary(AnalyzerMetadata metadata, 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);
    }
  }
}
