// Copyright (c) 2020, 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:typed_data';

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type_algebra.dart';
import 'package:analyzer/src/summary2/ast_binary_tag.dart';
import 'package:analyzer/src/summary2/ast_binary_writer.dart';
import 'package:analyzer/src/summary2/binary_format_doc.dart';
import 'package:analyzer/src/summary2/data_writer.dart';
import 'package:analyzer/src/summary2/reference.dart';

Uint8List writeUnitToBytes({required CompilationUnit unit}) {
  var byteSink = ByteSink();
  var sink = BufferedSink(byteSink);
  var stringIndexer = StringIndexer();

  var headerOffset = sink.offset;
  var nextResolutionIndex = 0;
  var unitWriter = AstBinaryWriter(
    withInformative: true,
    sink: sink,
    stringIndexer: stringIndexer,
    getNextResolutionIndex: () => nextResolutionIndex++,
    resolutionSink: null,
  );
  unit.accept(unitWriter);

  void _writeStringReference(String string) {
    var index = stringIndexer[string];
    sink.writeUInt30(index);
  }

  var indexOffset = sink.offset;
  sink.writeUInt30(unitWriter.unitMemberIndexItems.length);
  for (var declaration in unitWriter.unitMemberIndexItems) {
    sink.writeUInt30(declaration.offset);
    sink.writeByte(declaration.tag);
    declaration.name.map((name) {
      _writeStringReference(name);
    }, (variableNames) {
      sink.writeList(variableNames, _writeStringReference);
    });
    if (declaration.classIndexOffset != 0) {
      sink.writeUInt30(declaration.classIndexOffset);
    }
  }

  var libraryDataOffset = sink.offset;
  {
    var name = '';
    var nameOffset = -1;
    var nameLength = 0;
    for (var directive in unit.directives) {
      if (directive is LibraryDirective) {
        name = directive.name.components.map((e) => e.name).join('.');
        nameOffset = directive.name.offset;
        nameLength = directive.name.length;
        break;
      }
    }

    var hasPartOfDirective = false;
    for (var directive in unit.directives) {
      if (directive is PartOfDirective) {
        hasPartOfDirective = true;
        break;
      }
    }
    _writeStringReference(name);
    sink.writeUInt30(nameOffset + 1);
    sink.writeUInt30(nameLength);
    sink.writeByte(hasPartOfDirective ? 1 : 0);
    sink.writeByte(1); // withInformative
  }

  var stringTableOffset = stringIndexer.write(sink);

  sink.writeUInt32(headerOffset);
  sink.writeUInt32(indexOffset);
  sink.writeUInt32(libraryDataOffset);
  sink.writeUInt32(stringTableOffset);

  sink.flushAndDestroy();
  return byteSink.builder.takeBytes();
}

class BundleWriter {
  final bool withInformative;
  late final BundleWriterAst _astWriter;
  late final BundleWriterResolution _resolutionWriter;

  BundleWriter(this.withInformative, Reference dynamicReference) {
    _astWriter = BundleWriterAst(withInformative);
    _resolutionWriter = BundleWriterResolution(dynamicReference);
  }

  void addLibraryAst(LibraryToWriteAst library) {
    var astUnitOffsets = <int>[];
    for (var unit in library.units) {
      var offset = _astWriter.writeUnit(unit.node);
      astUnitOffsets.add(offset);
    }
    _astWriter.writeLibrary(library.units[0].node, astUnitOffsets);
  }

  void addLibraryResolution(LibraryToWriteResolution library) {
    var resolutionLibrary = _resolutionWriter.enterLibrary(library);
    for (var unit in library.units) {
      var resolutionUnit = resolutionLibrary.enterUnit(unit);
      // TODO(scheglov) Is it better to have a throwaway Object, or null?
      var notUsedSink = BufferedSink(ByteSink());
      var notUsedStringIndexer = StringIndexer();
      var unitWriter = AstBinaryWriter(
        withInformative: withInformative,
        sink: notUsedSink,
        stringIndexer: notUsedStringIndexer,
        getNextResolutionIndex: resolutionUnit.enterDeclaration,
        resolutionSink: resolutionUnit.library.sink,
      );
      unit.node.accept(unitWriter);
    }
  }

  BundleWriterResult finish() {
    var astBytes = _astWriter.finish();
    var resolutionBytes = _resolutionWriter.finish();
    return BundleWriterResult(
      astBytes: astBytes,
      resolutionBytes: resolutionBytes,
    );
  }
}

class BundleWriterAst {
  final bool withInformative;
  final ByteSink _byteSink = ByteSink();
  late final BufferedSink sink;
  final StringIndexer stringIndexer = StringIndexer();

  final List<int> _libraryOffsets = [];

  BundleWriterAst(this.withInformative) {
    sink = BufferedSink(_byteSink);
    sink.writeByte(withInformative ? 1 : 0);
  }

  Uint8List finish() {
    var librariesOffset = sink.offset;
    sink.writeUint30List(_libraryOffsets);

    var stringTableOffset = stringIndexer.write(sink);

    sink.writeUInt32(librariesOffset);
    sink.writeUInt32(stringTableOffset);

    sink.flushAndDestroy();
    return _byteSink.builder.takeBytes();
  }

  /// Write the library name and offset, and pointers to [unitOffsets].
  void writeLibrary(CompilationUnit definingUnit, List<int> unitOffsets) {
    _libraryOffsets.add(sink.offset);

    var name = '';
    var nameOffset = -1;
    var nameLength = 0;
    for (var directive in definingUnit.directives) {
      if (directive is LibraryDirective) {
        name = directive.name.components.map((e) => e.name).join('.');
        nameOffset = directive.name.offset;
        nameLength = directive.name.length;
        break;
      }
    }

    var hasPartOfDirective = false;
    for (var directive in definingUnit.directives) {
      if (directive is PartOfDirective) {
        hasPartOfDirective = true;
        break;
      }
    }

    _writeStringReference(name);
    sink.writeUInt30(1 + nameOffset);
    sink.writeUInt30(nameLength);
    sink.writeByte(hasPartOfDirective ? 1 : 0);
    sink.writeUint30List(unitOffsets);
  }

  /// Write the [node] into the [sink].
  ///
  /// Return the pointer at [AstUnitFormat.headerOffset].
  ///
  /// TODO(scheglov) looks very similar to [writeUnitToBytes]
  int writeUnit(CompilationUnit node) {
    var headerOffset = sink.offset;

    var nextResolutionIndex = 0;
    var unitWriter = AstBinaryWriter(
      withInformative: withInformative,
      sink: sink,
      stringIndexer: stringIndexer,
      getNextResolutionIndex: () => nextResolutionIndex++,
      resolutionSink: null,
    );
    node.accept(unitWriter);

    var indexOffset = sink.offset;
    sink.writeUInt30(headerOffset);

    sink.writeUInt30(unitWriter.unitMemberIndexItems.length);
    for (var declaration in unitWriter.unitMemberIndexItems) {
      sink.writeUInt30(declaration.offset);
      sink.writeByte(declaration.tag);
      declaration.name.map((name) {
        _writeStringReference(name);
      }, (variableNames) {
        sink.writeList(variableNames, _writeStringReference);
      });
      if (declaration.classIndexOffset != 0) {
        sink.writeUInt30(declaration.classIndexOffset);
      }
    }

    return indexOffset;
  }

  void _writeStringReference(String string) {
    var index = stringIndexer[string];
    sink.writeUInt30(index);
  }
}

class BundleWriterResolution {
  late final _BundleWriterReferences _references;
  final ByteSink _byteSink = ByteSink();
  late final BufferedSink _sink;
  late final ResolutionSink _resolutionSink;

  final StringIndexer _stringIndexer = StringIndexer();

  final List<_ResolutionLibrary> _libraries = [];

  BundleWriterResolution(Reference dynamicReference) {
    _references = _BundleWriterReferences(dynamicReference);

    _sink = BufferedSink(_byteSink);
    _resolutionSink = ResolutionSink(
      stringIndexer: _stringIndexer,
      sink: _sink,
      references: _references,
    );
  }

  _ResolutionLibrary enterLibrary(LibraryToWriteResolution libraryToWrite) {
    var library = _ResolutionLibrary(
      sink: _resolutionSink,
      library: libraryToWrite,
    );
    _libraries.add(library);
    return library;
  }

  Uint8List finish() {
    var libraryOffsets = <int>[];
    for (var library in _libraries) {
      var unitOffsets = <int>[];
      for (var unit in library.units) {
        unitOffsets.add(_sink.offset);
        _writeStringReference(unit.unit.uriStr);
        _sink.writeByte(unit.unit.isSynthetic ? 1 : 0);
        _sink.writeByte(unit.unit.partUriStr != null ? 1 : 0);
        _writeStringReference(unit.unit.partUriStr ?? '');
        _sink.writeUInt30(unit.directivesOffset);
        _sink.writeUint30List(unit.offsets);
      }
      libraryOffsets.add(_sink.offset);
      _writeStringReference(library.library.uriStr);
      _sink.writeUint30List(unitOffsets);
      _writeReferences(library.library.exports);
    }

    _references._clearIndexes();

    var librariesOffset = _sink.offset;
    _sink.writeUint30List(libraryOffsets);

    var referencesOffset = _sink.offset;
    _sink.writeUint30List(_references._referenceParents);
    _writeStringList(_references._referenceNames);

    var stringTableOffset = _stringIndexer.write(_sink);

    // Write as Uint32 so that we know where it is.
    _sink.writeUInt32(librariesOffset);
    _sink.writeUInt32(referencesOffset);
    _sink.writeUInt32(stringTableOffset);

    _sink.flushAndDestroy();
    return _byteSink.builder.takeBytes();
  }

  void _writeReferences(List<Reference> references) {
    var length = references.length;
    _sink.writeUInt30(length);

    for (var reference in references) {
      var index = _references._indexOfReference(reference);
      _sink.writeUInt30(index);
    }
  }

  void _writeStringList(List<String> values) {
    _sink.writeUInt30(values.length);
    for (var value in values) {
      _writeStringReference(value);
    }
  }

  void _writeStringReference(String string) {
    var index = _stringIndexer[string];
    _sink.writeUInt30(index);
  }
}

class BundleWriterResult {
  final Uint8List astBytes;
  final Uint8List resolutionBytes;

  BundleWriterResult({
    required this.astBytes,
    required this.resolutionBytes,
  });
}

class LibraryToWriteAst {
  final List<UnitToWriteAst> units;

  LibraryToWriteAst({
    required this.units,
  });
}

class LibraryToWriteResolution {
  final String uriStr;
  final List<Reference> exports;
  final List<UnitToWriteResolution> units;

  LibraryToWriteResolution({
    required this.uriStr,
    required this.exports,
    required this.units,
  });
}

class ResolutionSink {
  final StringIndexer _stringIndexer;
  final BufferedSink _sink;
  final _BundleWriterReferences _references2;
  final _LocalElementIndexer localElements = _LocalElementIndexer();

  ResolutionSink({
    required StringIndexer stringIndexer,
    required BufferedSink sink,
    required _BundleWriterReferences references,
  })   : _stringIndexer = stringIndexer,
        _sink = sink,
        _references2 = references;

  int get offset => _sink.offset;

  void writeByte(int byte) {
    assert((byte & 0xFF) == byte);
    _sink.addByte(byte);
  }

  /// TODO(scheglov) Triage places where we write elements.
  /// Some of then cannot be members, e.g. type names.
  void writeElement(Element? element) {
    if (element is Member) {
      var declaration = element.declaration;
      var isLegacy = element.isLegacy;

      var typeArguments = _enclosingClassTypeArguments(
        declaration,
        element.substitution.map,
      );

      writeByte(
        isLegacy
            ? Tag.MemberLegacyWithTypeArguments
            : Tag.MemberWithTypeArguments,
      );

      writeElement0(declaration);
      _writeTypeList(typeArguments);
    } else {
      writeByte(Tag.RawElement);
      writeElement0(element);
    }
  }

  void writeElement0(Element? element) {
    assert(element is! Member, 'Use writeMemberOrElement()');
    var elementIndex = _indexOfElement(element);
    _sink.writeUInt30(elementIndex);
  }

  void writeStringList(List<String> values) {
    _sink.writeUInt30(values.length);
    for (var value in values) {
      _writeStringReference(value);
    }
  }

  void writeType(DartType? type) {
    if (type == null) {
      writeByte(Tag.NullType);
    } else if (type is DynamicType) {
      writeByte(Tag.DynamicType);
      _writeTypeAliasElementArguments(type);
    } else if (type is FunctionType) {
      _writeFunctionType(type);
      _writeTypeAliasElementArguments(type);
    } else if (type is InterfaceType) {
      var typeArguments = type.typeArguments;
      var nullabilitySuffix = type.nullabilitySuffix;
      if (typeArguments.isEmpty) {
        if (nullabilitySuffix == NullabilitySuffix.none) {
          writeByte(Tag.InterfaceType_noTypeArguments_none);
        } else if (nullabilitySuffix == NullabilitySuffix.question) {
          writeByte(Tag.InterfaceType_noTypeArguments_question);
        } else if (nullabilitySuffix == NullabilitySuffix.star) {
          writeByte(Tag.InterfaceType_noTypeArguments_star);
        }
        // TODO(scheglov) Write raw
        writeElement(type.element);
      } else {
        writeByte(Tag.InterfaceType);
        // TODO(scheglov) Write raw
        writeElement(type.element);
        _sink.writeUInt30(typeArguments.length);
        for (var i = 0; i < typeArguments.length; ++i) {
          writeType(typeArguments[i]);
        }
        _writeNullabilitySuffix(nullabilitySuffix);
      }
      _writeTypeAliasElementArguments(type);
    } else if (type is NeverType) {
      writeByte(Tag.NeverType);
      _writeNullabilitySuffix(type.nullabilitySuffix);
      _writeTypeAliasElementArguments(type);
    } else if (type is TypeParameterType) {
      writeByte(Tag.TypeParameterType);
      writeElement(type.element);
      _writeNullabilitySuffix(type.nullabilitySuffix);
      _writeTypeAliasElementArguments(type);
    } else if (type is VoidType) {
      writeByte(Tag.VoidType);
      _writeTypeAliasElementArguments(type);
    } else {
      throw UnimplementedError('${type.runtimeType}');
    }
  }

  void writeUInt30(int value) {
    _sink.writeUInt30(value);
  }

  int _indexOfElement(Element? element) {
    if (element == null) return 0;
    if (element is MultiplyDefinedElement) return 0;
    assert(element is! Member);

    // Positional parameters cannot be referenced outside of their scope,
    // so don't have a reference, so are stored as local elements.
    if (element is ParameterElementImpl && element.reference == null) {
      return localElements[element] << 1 | 0x1;
    }

    // Type parameters cannot be referenced outside of their scope,
    // so don't have a reference, so are stored as local elements.
    if (element is TypeParameterElement) {
      return localElements[element] << 1 | 0x1;
    }

    if (identical(element, DynamicElementImpl.instance)) {
      return _references2._indexOfReference(_references2.dynamicReference) << 1;
    }

    var reference = (element as ElementImpl).reference;
    return _references2._indexOfReference(reference) << 1;
  }

  void _writeFormalParameterKind(ParameterElement p) {
    if (p.isRequiredPositional) {
      writeByte(Tag.ParameterKindRequiredPositional);
    } else if (p.isOptionalPositional) {
      writeByte(Tag.ParameterKindOptionalPositional);
    } else if (p.isRequiredNamed) {
      writeByte(Tag.ParameterKindRequiredNamed);
    } else if (p.isOptionalNamed) {
      writeByte(Tag.ParameterKindOptionalNamed);
    } else {
      throw StateError('Unexpected parameter kind: $p');
    }
  }

  void _writeFunctionType(FunctionType type) {
    type = _toSyntheticFunctionType(type);

    writeByte(Tag.FunctionType);

    localElements.pushScope();

    var typeParameters = type.typeFormals;
    for (var typeParameter in type.typeFormals) {
      localElements.declare(typeParameter);
    }

    _sink.writeUInt30(typeParameters.length);
    for (var typeParameter in type.typeFormals) {
      _writeStringReference(typeParameter.name);
    }
    for (var typeParameter in type.typeFormals) {
      writeType(typeParameter.bound);
    }

    writeType(type.returnType);

    var parameters = type.parameters;
    _sink.writeUInt30(parameters.length);
    for (var parameter in parameters) {
      _writeFormalParameterKind(parameter);
      writeType(parameter.type);
      // TODO(scheglov) Don't write names of positional parameters
      _writeStringReference(parameter.name);
    }

    _writeNullabilitySuffix(type.nullabilitySuffix);

    localElements.popScope();
  }

  void _writeNullabilitySuffix(NullabilitySuffix suffix) {
    writeByte(suffix.index);
  }

  void _writeStringReference(String string) {
    var index = _stringIndexer[string];
    _sink.writeUInt30(index);
  }

  void _writeTypeAliasElementArguments(DartType type) {
    var aliasElement = type.aliasElement;
    writeElement0(aliasElement);
    if (aliasElement != null) {
      _writeTypeList(type.aliasArguments!);
    }
  }

  void _writeTypeList(List<DartType> types) {
    _sink.writeUInt30(types.length);
    for (var type in types) {
      writeType(type);
    }
  }

  static List<DartType> _enclosingClassTypeArguments(
    Element declaration,
    Map<TypeParameterElement, DartType> substitution,
  ) {
    // TODO(scheglov) Just keep it null in class Member?
    if (substitution.isEmpty) {
      return const [];
    }

    var enclosing = declaration.enclosingElement;
    if (enclosing is TypeParameterizedElement) {
      if (enclosing is! ClassElement && enclosing is! ExtensionElement) {
        return const <DartType>[];
      }

      var typeParameters = enclosing.typeParameters;
      if (typeParameters.isEmpty) {
        return const <DartType>[];
      }

      return typeParameters
          .map((typeParameter) => substitution[typeParameter]!)
          .toList(growable: false);
    }

    return const <DartType>[];
  }

  static FunctionType _toSyntheticFunctionType(FunctionType type) {
    var typeParameters = type.typeFormals;

    if (typeParameters.isEmpty) return type;

    var onlySyntheticTypeParameters = typeParameters.every((e) {
      return e is TypeParameterElementImpl && e.linkedNode == null;
    });
    if (onlySyntheticTypeParameters) return type;

    var parameters = getFreshTypeParameters(typeParameters);
    return parameters.applyToFunctionType(type);
  }
}

class ResolutionUnit {
  final _ResolutionLibrary library;
  final UnitToWriteResolution unit;

  /// The offset of the resolution data for directives.
  final int directivesOffset;

  /// The offsets of resolution data for each declaration - class, method, etc.
  final List<int> offsets = [];

  ResolutionUnit({
    required this.library,
    required this.unit,
    required this.directivesOffset,
  });

  /// Should be called on enter into a new declaration on which level
  /// resolution is stored, e.g. [ClassDeclaration] (header), or
  /// [MethodDeclaration] (header), or [FieldDeclaration] (all).
  int enterDeclaration() {
    var index = offsets.length;
    offsets.add(library.sink.offset);
    return index;
  }
}

class StringIndexer {
  final Map<String, int> _index = {};

  int operator [](String string) {
    var result = _index[string];

    if (result == null) {
      result = _index.length;
      _index[string] = result;
    }

    return result;
  }

  int write(BufferedSink sink) {
    var bytesOffset = sink.offset;

    var length = _index.length;
    var lengths = Uint32List(length);
    var lengthsIndex = 0;
    for (var key in _index.keys) {
      var stringStart = sink.offset;
      _writeWtf8(sink, key);
      lengths[lengthsIndex++] = sink.offset - stringStart;
    }

    var resultOffset = sink.offset;

    var lengthOfBytes = sink.offset - bytesOffset;
    sink.writeUInt30(lengthOfBytes);
    sink.writeUint30List(lengths);

    return resultOffset;
  }

  /// Write [source] string into [sink].
  static void _writeWtf8(BufferedSink sink, String source) {
    var end = source.length;
    if (end == 0) {
      return;
    }

    int i = 0;
    do {
      var codeUnit = source.codeUnitAt(i++);
      if (codeUnit < 128) {
        // ASCII.
        sink.addByte(codeUnit);
      } else if (codeUnit < 0x800) {
        // Two-byte sequence (11-bit unicode value).
        sink.addByte(0xC0 | (codeUnit >> 6));
        sink.addByte(0x80 | (codeUnit & 0x3f));
      } else if ((codeUnit & 0xFC00) == 0xD800 &&
          i < end &&
          (source.codeUnitAt(i) & 0xFC00) == 0xDC00) {
        // Surrogate pair -> four-byte sequence (non-BMP unicode value).
        int codeUnit2 = source.codeUnitAt(i++);
        int unicode =
            0x10000 + ((codeUnit & 0x3FF) << 10) + (codeUnit2 & 0x3FF);
        sink.addByte(0xF0 | (unicode >> 18));
        sink.addByte(0x80 | ((unicode >> 12) & 0x3F));
        sink.addByte(0x80 | ((unicode >> 6) & 0x3F));
        sink.addByte(0x80 | (unicode & 0x3F));
      } else {
        // Three-byte sequence (16-bit unicode value), including lone
        // surrogates.
        sink.addByte(0xE0 | (codeUnit >> 12));
        sink.addByte(0x80 | ((codeUnit >> 6) & 0x3f));
        sink.addByte(0x80 | (codeUnit & 0x3f));
      }
    } while (i < end);
  }
}

class UnitToWriteAst {
  final CompilationUnit node;

  UnitToWriteAst({
    required this.node,
  });
}

class UnitToWriteResolution {
  final String uriStr;
  final String? partUriStr;
  final CompilationUnit node;
  final bool isSynthetic;

  UnitToWriteResolution({
    required this.uriStr,
    required this.partUriStr,
    required this.node,
    required this.isSynthetic,
  });
}

class _BundleWriterReferences {
  /// The `dynamic` class is declared in `dart:core`, but is not a class.
  /// Also, it is static, so we cannot set `reference` for it.
  /// So, we have to push it in a separate way.
  final Reference dynamicReference;

  /// References used in all libraries being linked.
  /// Element references in nodes are indexes in this list.
  /// TODO(scheglov) Do we really use this list?
  final List<Reference?> references = [null];

  final List<int> _referenceParents = [0];
  final List<String> _referenceNames = [''];

  _BundleWriterReferences(this.dynamicReference);

  /// We need indexes for references during linking, but once we are done,
  /// we must clear indexes to make references ready for linking a next bundle.
  void _clearIndexes() {
    for (var reference in references) {
      if (reference != null) {
        reference.index = null;
      }
    }
  }

  int _indexOfReference(Reference? reference) {
    if (reference == null) return 0;
    if (reference.parent == null) return 0;

    var index = reference.index;
    if (index != null) return index;

    var parentIndex = _indexOfReference(reference.parent);
    _referenceParents.add(parentIndex);
    _referenceNames.add(reference.name);

    index = references.length;
    reference.index = index;
    references.add(reference);
    return index;
  }
}

class _LocalElementIndexer {
  final Map<Element, int> _index = Map.identity();
  final List<int> _scopes = [];
  int _stackHeight = 0;

  int operator [](Element element) {
    return _index[element] ??
        (throw ArgumentError('Unexpectedly not indexed: $element'));
  }

  void declare(Element element) {
    _index[element] = _stackHeight++;
  }

  void popScope() {
    _stackHeight = _scopes.removeLast();
  }

  void pushScope() {
    _scopes.add(_stackHeight);
  }
}

class _ResolutionLibrary {
  final ResolutionSink sink;
  final LibraryToWriteResolution library;
  final List<ResolutionUnit> units = [];

  _ResolutionLibrary({
    required this.sink,
    required this.library,
  });

  ResolutionUnit enterUnit(UnitToWriteResolution unitToWrite) {
    var unit = ResolutionUnit(
      library: this,
      unit: unitToWrite,
      directivesOffset: sink.offset,
    );
    units.add(unit);
    return unit;
  }
}
