// Copyright (c) 2018, 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:async';
import 'dart:typed_data';

import 'package:kernel/ast.dart' as ir;
import 'package:kernel/binary/ast_from_binary.dart' as ir;
import 'package:kernel/binary/ast_to_binary.dart' as ir;

import '../../compiler_api.dart' as api;
import '../common/codegen.dart';
import '../common/tasks.dart';
import '../deferred_load/output_unit.dart';
import '../diagnostics/diagnostic_listener.dart';
import '../dump_info.dart';
import '../elements/entities.dart';
import '../environment.dart';
import '../inferrer/abstract_value_domain.dart';
import '../inferrer/abstract_value_strategy.dart';
import '../inferrer/types.dart';
import '../io/source_information.dart';
import '../js_backend/codegen_inputs.dart';
import '../js_backend/inferred_data.dart';
import '../js_model/js_strategy.dart';
import '../js_model/js_world.dart';
import '../js_model/locals.dart';
import '../options.dart';
import 'deferrable.dart';
import 'serialization.dart';

class _StringInterner implements ir.StringInterner, StringInterner {
  final Map<String, String> _map = {};

  @override
  String internString(String string) {
    return _map[string] ??= string;
  }
}

class SerializationTask extends CompilerTask {
  final CompilerOptions _options;
  final DiagnosticReporter _reporter;
  final api.CompilerInput _provider;
  final api.CompilerOutput _outputProvider;
  final _stringInterner = _StringInterner();
  final ValueInterner? _valueInterner;

  SerializationTask(
    this._options,
    this._reporter,
    this._provider,
    this._outputProvider,
    Measurer measurer,
  ) : _valueInterner = _options.features.internValues.isEnabled
          ? ValueInterner()
          : null,
      super(measurer);

  @override
  String get name => 'Serialization';

  void serializeComponent(
    ir.Component component, {
    bool includeSourceBytes = true,
  }) {
    measureSubtask('serialize dill', () {
      _reporter.log('Writing dill to ${_options.outputUri}');
      api.BinaryOutputSink dillOutput = _outputProvider.createBinarySink(
        _options.outputUri!,
      );
      ir.BinaryPrinter printer = ir.BinaryPrinter(
        dillOutput,
        includeSourceBytes: includeSourceBytes,
      );
      printer.writeComponentFile(component);
      dillOutput.close();
    });
  }

  Future<ir.Component> deserializeComponent() async {
    return measureIoSubtask('deserialize dill', () async {
      _reporter.log('Reading dill from ${_options.inputDillUri}');
      final dillInput = await _provider.readFromUri(
        _options.inputDillUri,
        inputKind: api.InputKind.binary,
      );
      ir.Component component = ir.Component();
      // Not using growable lists saves memory.
      ir.BinaryBuilder(
        dillInput.data,
        useGrowableLists: false,
        stringInterner: _stringInterner,
      ).readComponent(component);
      return component;
    });
  }

  Future<ir.Component> deserializeComponentAndUpdateOptions() async {
    ir.Component component = await deserializeComponent();
    return component;
  }

  void serializeClosedWorld(
    JClosedWorld closedWorld,
    SerializationIndices indices,
  ) {
    measureSubtask('serialize closed world', () {
      final outputUri = _options.dataUriForStage(CompilerStage.closedWorld);
      _reporter.log('Writing closed world to $outputUri');
      api.BinaryOutputSink dataOutput = _outputProvider.createBinarySink(
        outputUri,
      );
      DataSinkWriter sink = DataSinkWriter(
        BinaryDataSink(dataOutput),
        _options,
        indices,
      );
      serializeClosedWorldToSink(closedWorld, sink);
    });
  }

  Future<JClosedWorld> deserializeClosedWorld(
    AbstractValueStrategy abstractValueStrategy,
    ir.Component component,
    bool useDeferredSourceReads,
    SerializationIndices indices,
  ) async {
    return await measureIoSubtask('deserialize closed world', () async {
      final uri = _options.dataUriForStage(CompilerStage.closedWorld);
      _reporter.log('Reading data from $uri');
      api.Input<Uint8List> dataInput = await _provider.readFromUri(
        uri,
        inputKind: api.InputKind.binary,
      );
      DataSourceReader source = DataSourceReader(
        BinaryDataSource(dataInput.data, stringInterner: _stringInterner),
        _options,
        indices,
        interner: _valueInterner,
        useDeferredStrategy: useDeferredSourceReads,
      );
      var closedWorld = deserializeClosedWorldFromSource(
        _options,
        _reporter,
        abstractValueStrategy,
        component,
        source,
      );
      return closedWorld;
    });
  }

  void serializeGlobalTypeInference(
    GlobalTypeInferenceResults results,
    SerializationIndices indices,
  ) {
    measureSubtask('serialize data', () {
      final outputUri = _options.dataUriForStage(CompilerStage.globalInference);
      _reporter.log('Writing data to $outputUri');
      api.BinaryOutputSink dataOutput = _outputProvider.createBinarySink(
        outputUri,
      );
      DataSinkWriter sink = DataSinkWriter(
        BinaryDataSink(dataOutput),
        _options,
        indices,
      );
      serializeGlobalTypeInferenceResultsToSink(results, sink);
    });
  }

  Future<GlobalTypeInferenceResults> deserializeGlobalTypeInferenceResults(
    Environment environment,
    AbstractValueStrategy abstractValueStrategy,
    ir.Component component,
    JClosedWorld closedWorld,
    bool useDeferredSourceReads,
    SerializationIndices indices,
  ) async {
    return await measureIoSubtask('deserialize data', () async {
      final uri = _options.dataUriForStage(CompilerStage.globalInference);
      _reporter.log('Reading data from $uri');
      api.Input<Uint8List> dataInput = await _provider.readFromUri(
        uri,
        inputKind: api.InputKind.binary,
      );
      DataSourceReader source = DataSourceReader(
        BinaryDataSource(dataInput.data, stringInterner: _stringInterner),
        _options,
        indices,
        interner: _valueInterner,
        useDeferredStrategy: useDeferredSourceReads,
      );
      return deserializeGlobalTypeInferenceResultsFromSource(
        _options,
        _reporter,
        environment,
        abstractValueStrategy,
        component,
        closedWorld,
        source,
      );
    });
  }

  void serializeCodegen(
    JsBackendStrategy backendStrategy,
    AbstractValueDomain domain,
    CodegenResults codegenResults,
    SerializationIndices indices,
  ) {
    int shard = _options.codegenShard!;
    int shards = _options.codegenShards!;
    Map<MemberEntity, CodegenResult> results = {};
    int index = 0;
    final lazyMemberBodies = backendStrategy.forEachCodegenMember((
      MemberEntity member,
    ) {
      if (index % shards == shard) {
        final (result: codegenResult, isGenerated: _) = codegenResults
            .getCodegenResults(member);
        results[member] = codegenResult;
      }
      index++;
    });
    measureSubtask('serialize codegen', () {
      final outputUri = _options.dataUriForStage(CompilerStage.codegenSharded);
      Uri uri = Uri.parse('$outputUri$shard');
      api.BinaryOutputSink dataOutput = _outputProvider.createBinarySink(uri);
      DataSinkWriter sink = DataSinkWriter(
        BinaryDataSink(dataOutput),
        _options,
        indices,
      );
      _reporter.log('Writing data to $uri');
      sink.writeMembers(lazyMemberBodies);
      sink.registerAbstractValueDomain(domain);
      sink.writeMemberMap(results, (MemberEntity member, CodegenResult result) {
        sink.writeDeferrable(() => result.writeToDataSink(sink));
      });
      sink.close();
    });
  }

  Future<CodegenResults> deserializeCodegen(
    JsBackendStrategy backendStrategy,
    JClosedWorld closedWorld,
    CodegenInputs codegenInputs,
    bool useDeferredSourceReads,
    SourceLookup sourceLookup,
    SerializationIndices indices,
  ) async {
    int shards = _options.codegenShards!;
    Map<MemberEntity, Deferrable<CodegenResult>> results = {};
    for (int shard = 0; shard < shards; shard++) {
      Uri uri = Uri.parse(
        '${_options.dataUriForStage(CompilerStage.codegenSharded)}$shard',
      );
      await measureIoSubtask('deserialize codegen', () async {
        _reporter.log('Reading data from $uri');
        api.Input<Uint8List> dataInput = await _provider.readFromUri(
          uri,
          inputKind: api.InputKind.binary,
        );
        // TODO(36983): This code is extracted because there appeared to be a
        // memory leak for large buffer held by `source`.
        _deserializeCodegenInput(
          backendStrategy,
          closedWorld,
          uri,
          dataInput,
          results,
          useDeferredSourceReads,
          sourceLookup,
          indices,
        );
        dataInput.release();
      });
    }
    return DeserializedCodegenResults(
      codegenInputs,
      DeferrableValueMap(results),
      backendStrategy.functionCompiler,
    );
  }

  void _deserializeCodegenInput(
    JsBackendStrategy backendStrategy,
    JClosedWorld closedWorld,
    Uri uri,
    api.Input<Uint8List> dataInput,
    Map<MemberEntity, Deferrable<CodegenResult>> results,
    bool useDeferredSourceReads,
    SourceLookup sourceLookup,
    SerializationIndices indices,
  ) {
    DataSourceReader source = DataSourceReader(
      BinaryDataSource(dataInput.data, stringInterner: _stringInterner),
      _options,
      indices,
      interner: _valueInterner,
      useDeferredStrategy: useDeferredSourceReads,
    );
    backendStrategy.prepareCodegenReader(source);
    source.registerSourceLookup(sourceLookup);
    final lazyMemberBodies = source.readMembers();
    closedWorld.elementMap.registerLazyMemberBodies(lazyMemberBodies);
    source.registerAbstractValueDomain(closedWorld.abstractValueDomain);
    Map<MemberEntity, Deferrable<CodegenResult>> codegenResults = source
        .readMemberMap((MemberEntity member) {
          return source.readDeferrable(
            CodegenResult.readFromDataSource,
            cacheData: false,
          );
        });
    _reporter.log('Read ${codegenResults.length} members from $uri');
    results.addAll(codegenResults);
  }

  DataSinkWriter dataSinkWriterForDumpInfo(
    AbstractValueDomain abstractValueDomain,
    SerializationIndices indices,
  ) {
    final outputUri = _options.dataUriForStage(CompilerStage.dumpInfo);
    api.BinaryOutputSink dataOutput = _outputProvider.createBinarySink(
      outputUri,
    );
    final sink = DataSinkWriter(BinaryDataSink(dataOutput), _options, indices);
    sink.registerAbstractValueDomain(abstractValueDomain);
    return sink;
  }

  void serializeDumpInfoProgramData(
    DataSinkWriter sink,
    JsBackendStrategy backendStrategy,
    DumpInfoProgramData dumpInfoProgramData,
    DumpInfoJsAstRegistry dumpInfoRegistry,
  ) {
    dumpInfoProgramData.writeToDataSink(sink, dumpInfoRegistry);
    sink.close();
  }

  Future<DumpInfoProgramData> deserializeDumpInfoProgramData(
    JsBackendStrategy backendStrategy,
    AbstractValueDomain abstractValueDomain,
    OutputUnitData outputUnitData,
    SerializationIndices indices,
  ) async {
    final inputUri = _options.dataUriForStage(CompilerStage.dumpInfo);
    final dataInput = await _provider.readFromUri(
      inputUri,
      inputKind: api.InputKind.binary,
    );
    final source = DataSourceReader(
      BinaryDataSource(dataInput.data, stringInterner: _stringInterner),
      _options,
      indices,
      // This must use a deferred strategy so that we can delay reading the
      // registered impacts until we are able to read the count of them.
      useDeferredStrategy: true,
    );
    backendStrategy.prepareCodegenReader(source);
    source.registerAbstractValueDomain(abstractValueDomain);
    return DumpInfoProgramData.readFromDataSource(
      source,
      includeCodeText: _options.dumpInfoFormat != DumpInfoFormat.binary,
    );
  }
}

void serializeGlobalTypeInferenceResultsToSink(
  GlobalTypeInferenceResults results,
  DataSinkWriter sink,
) {
  final closedWorld = results.closedWorld;
  GlobalLocalsMap globalLocalsMap = results.globalLocalsMap;
  InferredData inferredData = results.inferredData;
  globalLocalsMap.writeToDataSink(sink);
  inferredData.writeToDataSink(sink);
  results.writeToDataSink(sink, closedWorld.elementMap);
  sink.close();
}

GlobalTypeInferenceResults deserializeGlobalTypeInferenceResultsFromSource(
  CompilerOptions options,
  DiagnosticReporter reporter,
  Environment environment,
  AbstractValueStrategy abstractValueStrategy,
  ir.Component component,
  JClosedWorld closedWorld,
  DataSourceReader source,
) {
  source.registerComponentLookup(ComponentLookup(component));
  GlobalLocalsMap globalLocalsMap = GlobalLocalsMap.readFromDataSource(
    closedWorld.closureDataLookup.getEnclosingMember,
    source,
  );
  InferredData inferredData = InferredData.readFromDataSource(
    source,
    closedWorld,
  );
  return GlobalTypeInferenceResults.readFromDataSource(
    source,
    closedWorld.elementMap,
    closedWorld,
    globalLocalsMap,
    inferredData,
  );
}

void serializeClosedWorldToSink(JClosedWorld closedWorld, DataSinkWriter sink) {
  closedWorld.writeToDataSink(sink);
  sink.close();
}

JClosedWorld deserializeClosedWorldFromSource(
  CompilerOptions options,
  DiagnosticReporter reporter,
  AbstractValueStrategy abstractValueStrategy,
  ir.Component component,
  DataSourceReader source,
) {
  return JClosedWorld.readFromDataSource(
    options,
    reporter,
    abstractValueStrategy,
    component,
    source,
  );
}
