// Copyright (c) 2015, 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.

library dart2js.serialization.task;

import 'dart:async' show EventSink, Future;
import '../common/resolution.dart' show ResolutionImpact, ResolutionWorkItem;
import '../common/tasks.dart' show CompilerTask;
import '../common/work.dart' show ItemCompilationContext;
import '../compiler.dart' show Compiler;
import '../elements/elements.dart';
import '../enqueue.dart' show ResolutionEnqueuer;
import '../universe/world_impact.dart' show WorldImpact;
import 'json_serializer.dart';
import 'serialization.dart';
import 'system.dart';

/// A deserializer that can load a library element by reading it's information
/// from a serialized form.
abstract class LibraryDeserializer {
  /// Loads the [LibraryElement] associated with a library under [uri], or null
  /// if no serialized information is available for the given library.
  Future<LibraryElement> readLibrary(Uri uri);
}

/// Task that supports deserialization of elements.
class SerializationTask extends CompilerTask implements LibraryDeserializer {
  SerializationTask(Compiler compiler) : super(compiler);

  DeserializerSystem deserializer;

  String get name => 'Serialization';

  /// If `true`, data must be retained to support serialization.
  // TODO(johnniwinther): Make this more precise in terms of what needs to be
  // retained, for instance impacts, resolution data etc.
  bool supportSerialization = false;

  /// If `true`, deserialized data is supported.
  bool get supportsDeserialization => deserializer != null;

  /// Returns the [LibraryElement] for [resolvedUri] if available from
  /// serialization.
  Future<LibraryElement> readLibrary(Uri resolvedUri) {
    if (deserializer == null) return new Future<LibraryElement>.value();
    return deserializer.readLibrary(resolvedUri);
  }

  /// Returns `true` if [element] has been deserialized.
  bool isDeserialized(Element element) {
    return deserializer != null && deserializer.isDeserialized(element);
  }

  bool hasResolutionImpact(Element element) {
    return deserializer != null && deserializer.hasResolutionImpact(element);
  }

  ResolutionImpact getResolutionImpact(Element element) {
    return deserializer != null
        ? deserializer.getResolutionImpact(element)
        : null;
  }

  /// Creates the [ResolutionWorkItem] for the deserialized [element].
  ResolutionWorkItem createResolutionWorkItem(
      Element element, ItemCompilationContext context) {
    assert(deserializer != null);
    assert(isDeserialized(element));
    return new DeserializedResolutionWorkItem(
        element, context, deserializer.computeWorldImpact(element));
  }

  bool hasResolvedAst(ExecutableElement element) {
    return deserializer != null ? deserializer.hasResolvedAst(element) : false;
  }

  ResolvedAst getResolvedAst(ExecutableElement element) {
    return deserializer != null ? deserializer.getResolvedAst(element) : null;
  }

  Serializer createSerializer(Iterable<LibraryElement> libraries) {
    return measure(() {
      assert(supportSerialization);

      Serializer serializer = new Serializer();
      SerializerPlugin backendSerializer =
          compiler.backend.serialization.serializer;
      serializer.plugins.add(backendSerializer);
      serializer.plugins.add(new ResolutionImpactSerializer(
          compiler.resolution, backendSerializer));
      serializer.plugins.add(new ResolvedAstSerializerPlugin(
          compiler.resolution, backendSerializer));

      for (LibraryElement library in libraries) {
        serializer.serialize(library);
      }
      return serializer;
    });
  }

  void serializeToSink(
      EventSink<String> sink, Iterable<LibraryElement> libraries) {
    measure(() {
      sink
        ..add(createSerializer(libraries)
            .toText(const JsonSerializationEncoder()))
        ..close();
    });
  }

  void deserializeFromText(String serializedData) {
    measure(() {
      Deserializer dataDeserializer = new Deserializer.fromText(
          new DeserializationContext(),
          serializedData,
          const JsonSerializationDecoder());
      dataDeserializer.plugins.add(compiler.backend.serialization.deserializer);
      deserializer = new DeserializerSystemImpl(
          compiler, dataDeserializer, compiler.backend.impactTransformer);
    });
  }
}

/// A [ResolutionWorkItem] for a deserialized element.
///
/// This will not resolve the element but only compute the [WorldImpact].
class DeserializedResolutionWorkItem implements ResolutionWorkItem {
  final Element element;
  final ItemCompilationContext compilationContext;
  final WorldImpact worldImpact;
  bool _isAnalyzed = false;

  DeserializedResolutionWorkItem(
      this.element, this.compilationContext, this.worldImpact);

  @override
  bool get isAnalyzed => _isAnalyzed;

  @override
  WorldImpact run(Compiler compiler, ResolutionEnqueuer world) {
    _isAnalyzed = true;
    world.registerProcessedElement(element);
    return worldImpact;
  }
}

/// The interface for a system that supports deserialization of libraries and
/// elements.
abstract class DeserializerSystem {
  Future<LibraryElement> readLibrary(Uri resolvedUri);
  bool isDeserialized(Element element);
  bool hasResolvedAst(ExecutableElement element);
  ResolvedAst getResolvedAst(ExecutableElement element);
  bool hasResolutionImpact(Element element);
  ResolutionImpact getResolutionImpact(Element element);
  WorldImpact computeWorldImpact(Element element);
}
