// 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();
  }
}

/// Index of metadata.
class AnalyzerMetadataIndex {
  final Map<kernel.Library, List<kernel.TreeNode>> libraryNodes = {};
  AnalyzerMetadataRepository repository;

  /// The [library] was invalidated, flush its metadata.
  void invalidate(kernel.Library library) {
    var nodes = libraryNodes.remove(library);
    nodes?.forEach(repository.mapping.remove);
  }

  /// A [newComponent] has been compiled, with new, and only new, metadata.
  /// Merge the existing [repository] into the new one, and replace it.
  void replaceComponent(kernel.Component newComponent) {
    AnalyzerMetadataRepository newRepository =
        newComponent.metadata[AnalyzerMetadataRepository.TAG];
    if (newRepository != null) {
      _indexNewMetadata(newRepository);
      if (repository != null) {
        newRepository.mapping.addAll(repository.mapping);
      }
      repository = newRepository;
    } else {
      newComponent.metadata[AnalyzerMetadataRepository.TAG] = repository;
    }
  }

  void _indexNewMetadata(AnalyzerMetadataRepository newRepository) {
    for (var node in newRepository.mapping.keys) {
      var library = _enclosingLibrary(node);
      assert(library != null);

      var nodes = libraryNodes[library];
      if (nodes == null) {
        nodes = <kernel.TreeNode>[];
        libraryNodes[library] = nodes;
      }

      nodes.add(node);
    }
  }

  static kernel.Library _enclosingLibrary(kernel.TreeNode node) {
    for (; node != null; node = node.parent) {
      if (node is kernel.Library) {
        return node;
      }
    }
    return null;
  }
}

/// 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);
    }
  }
}
