// Copyright (c) 2016, 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_system;

import 'dart:async';

import '../common.dart';
import '../common/resolution.dart';
import '../compiler.dart';
import '../dart_types.dart';
import '../elements/elements.dart';
import '../scanner/scanner.dart';
import '../script.dart';
import '../serialization/impact_serialization.dart';
import '../tokens/token.dart';
import '../universe/call_structure.dart';
import '../universe/use.dart';
import '../universe/world_impact.dart';
import 'modelz.dart';
import 'resolved_ast_serialization.dart';
import 'serialization.dart';
import 'task.dart';

class ResolutionDeserializerSystem extends DeserializerSystem {
  final Compiler _compiler;
  final Resolution resolution;
  final DeserializationContext deserializationContext;
  final List<LibraryElement> deserializedLibraries = <LibraryElement>[];

  factory ResolutionDeserializerSystem(Compiler compiler,
      {bool deserializeCompilationDataForTesting: false}) {
    DeserializationContext context = new DeserializationContext(
        compiler.reporter, compiler.resolution, compiler.libraryLoader);
    DeserializerPlugin backendDeserializer =
        compiler.backend.serialization.deserializer;
    context.plugins.add(backendDeserializer);
    if (compiler.options.resolveOnly && !deserializeCompilationDataForTesting) {
      return new ResolutionDeserializerSystem._(
          compiler, compiler.resolution, context);
    } else {
      ResolutionImpactDeserializer resolutionImpactDeserializer =
          new ResolutionImpactDeserializer(backendDeserializer);
      context.plugins.add(resolutionImpactDeserializer);
      ResolvedAstDeserializerPlugin resolvedAstDeserializer =
          new ResolvedAstDeserializerPlugin(
              compiler.parsingContext, backendDeserializer);
      context.plugins.add(resolvedAstDeserializer);
      return new CompilationDeserializerSystem._(compiler, compiler.resolution,
          context, resolutionImpactDeserializer, resolvedAstDeserializer);
    }
  }

  ResolutionDeserializerSystem._(
      this._compiler, this.resolution, this.deserializationContext);

  @override
  Future<LibraryElement> readLibrary(Uri resolvedUri) {
    LibraryElement library = deserializationContext.lookupLibrary(resolvedUri);
    if (library != null) {
      deserializedLibraries.add(library);
      return onReadLibrary(library);
    }
    return new Future<LibraryElement>.value(library);
  }

  Future<LibraryElement> onReadLibrary(LibraryElement library) {
    return new Future<LibraryElement>.value(library);
  }

  // TODO(johnniwinther): Remove the need for this method.
  @override
  bool hasResolvedAst(ExecutableElement element) {
    return getResolvedAst(element) != null;
  }

  @override
  ResolvedAst getResolvedAst(ExecutableElement element) => null;

  @override
  bool hasResolutionImpact(Element element) => true;

  @override
  ResolutionImpact getResolutionImpact(Element element) {
    return const ResolutionImpact();
  }

  @override
  WorldImpact computeWorldImpact(Element element) {
    ResolutionImpact resolutionImpact = getResolutionImpact(element);
    assert(invariant(element, resolutionImpact != null,
        message: 'No impact found for $element (${element.library})'));
    if (element is ExecutableElement) {
      getResolvedAst(element);
    }
    if (element.isField && !element.isConst) {
      FieldElement field = element;
      if (field.isTopLevel || field.isStatic) {
        if (field.constant == null) {
          // TODO(johnniwinther): Find a cleaner way to do this. Maybe
          // `Feature.LAZY_FIELD` of the resolution impact should be used
          // instead.
          _compiler.backend.constants.registerLazyStatic(element);
        }
      }
    }
    return resolution.transformResolutionImpact(element, resolutionImpact);
  }

  @override
  bool isDeserialized(Element element) {
    return deserializedLibraries.contains(element.library);
  }
}

class CompilationDeserializerSystem extends ResolutionDeserializerSystem {
  final ResolutionImpactDeserializer _resolutionImpactDeserializer;
  final ResolvedAstDeserializerPlugin _resolvedAstDeserializer;

  CompilationDeserializerSystem._(
      Compiler compiler,
      Resolution resolution,
      DeserializationContext deserializationContext,
      this._resolutionImpactDeserializer,
      this._resolvedAstDeserializer)
      : super._(compiler, resolution, deserializationContext);

  @override
  Future<LibraryElement> onReadLibrary(LibraryElement library) {
    return Future.forEach(library.compilationUnits,
        (CompilationUnitElement compilationUnit) {
      ScriptZ script = compilationUnit.script;
      return _compiler.readScript(script.readableUri).then((Script newScript) {
        script.file = newScript.file;
        script.isSynthesized = newScript.isSynthesized;
        _resolvedAstDeserializer.scripts[script.resourceUri] = script;
      });
    }).then((_) => library);
  }

  @override
  ResolvedAst getResolvedAst(ExecutableElement element) {
    return _resolvedAstDeserializer.getResolvedAst(element);
  }

  @override
  bool hasResolutionImpact(Element element) {
    if (element.isConstructor &&
        element.enclosingClass.isUnnamedMixinApplication) {
      return true;
    }
    return _resolutionImpactDeserializer.hasResolutionImpact(element);
  }

  @override
  ResolutionImpact getResolutionImpact(Element element) {
    if (element.isConstructor &&
        element.enclosingClass.isUnnamedMixinApplication) {
      ConstructorElement constructor = element;
      ClassElement superclass = constructor.enclosingClass.superclass;
      ConstructorElement superclassConstructor =
          superclass.lookupConstructor(constructor.name);
      assert(invariant(element, superclassConstructor != null,
          message: "Superclass constructor '${constructor.name}' called from "
              "${element} not found in ${superclass}."));
      // TODO(johnniwinther): Compute callStructure. Currently not used.
      CallStructure callStructure;
      return _resolutionImpactDeserializer.registerResolutionImpact(constructor,
          () {
        List<TypeUse> typeUses = <TypeUse>[];
        void addCheckedModeCheck(DartType type) {
          if (!type.isDynamic) {
            typeUses.add(new TypeUse.checkedModeCheck(type));
          }
        }

        FunctionType type = constructor.type;
        // TODO(johnniwinther): Remove this substitution when synthesized
        // constructors handle type variables correctly.
        type = type.substByContext(constructor.enclosingClass
            .asInstanceOf(constructor.enclosingClass));
        type.parameterTypes.forEach(addCheckedModeCheck);
        type.optionalParameterTypes.forEach(addCheckedModeCheck);
        type.namedParameterTypes.forEach(addCheckedModeCheck);
        return new DeserializedResolutionImpact(staticUses: <StaticUse>[
          new StaticUse.superConstructorInvoke(
              superclassConstructor, callStructure)
        ], typeUses: typeUses);
      });
    }
    return _resolutionImpactDeserializer.getResolutionImpact(element);
  }
}

const String WORLD_IMPACT_TAG = 'worldImpact';

class ResolutionImpactSerializer extends SerializerPlugin {
  final Resolution resolution;
  final SerializerPlugin nativeDataSerializer;

  ResolutionImpactSerializer(this.resolution, this.nativeDataSerializer);

  @override
  void onElement(Element element, ObjectEncoder createEncoder(String tag)) {
    if (resolution.hasBeenResolved(element)) {
      ResolutionImpact impact = resolution.getResolutionImpact(element);
      ObjectEncoder encoder = createEncoder(WORLD_IMPACT_TAG);
      new ImpactSerializer(element, encoder, nativeDataSerializer)
          .serialize(impact);
    }
  }
}

class ResolutionImpactDeserializer extends DeserializerPlugin {
  Map<Element, ObjectDecoder> _decoderMap = <Element, ObjectDecoder>{};
  Map<Element, ResolutionImpact> _impactMap = <Element, ResolutionImpact>{};
  final DeserializerPlugin nativeDataDeserializer;

  ResolutionImpactDeserializer(this.nativeDataDeserializer);

  @override
  void onElement(Element element, ObjectDecoder getDecoder(String tag)) {
    ObjectDecoder decoder = getDecoder(WORLD_IMPACT_TAG);
    if (decoder != null) {
      _decoderMap[element] = decoder;
    }
  }

  bool hasResolutionImpact(Element element) {
    return _impactMap.containsKey(element) || _decoderMap.containsKey(element);
  }

  ResolutionImpact registerResolutionImpact(
      Element element, ResolutionImpact ifAbsent()) {
    return _impactMap.putIfAbsent(element, ifAbsent);
  }

  ResolutionImpact getResolutionImpact(Element element) {
    return registerResolutionImpact(element, () {
      ObjectDecoder decoder = _decoderMap[element];
      if (decoder != null) {
        _decoderMap.remove(element);
        return ImpactDeserializer.deserializeImpact(
            element, decoder, nativeDataDeserializer);
      }
      return null;
    });
  }
}

const String RESOLVED_AST_TAG = 'resolvedAst';

class ResolvedAstSerializerPlugin extends SerializerPlugin {
  final Resolution resolution;
  final SerializerPlugin nativeDataSerializer;

  ResolvedAstSerializerPlugin(this.resolution, this.nativeDataSerializer);

  @override
  void onElement(Element element, ObjectEncoder createEncoder(String tag)) {
    assert(invariant(element, element.isDeclaration,
        message: "Element $element must be the declaration"));
    if (element.isError) return;
    if (element is MemberElement) {
      assert(invariant(element, resolution.hasResolvedAst(element),
          message: "Element $element must have a resolved ast"));
      ResolvedAst resolvedAst = resolution.getResolvedAst(element);
      ObjectEncoder objectEncoder = createEncoder(RESOLVED_AST_TAG);
      new ResolvedAstSerializer(
              objectEncoder, resolvedAst, nativeDataSerializer)
          .serialize();
    }
  }
}

class ResolvedAstDeserializerPlugin extends DeserializerPlugin {
  final ParsingContext parsingContext;
  final DeserializerPlugin nativeDataDeserializer;
  final Map<Uri, Script> scripts = <Uri, Script>{};

  Map<MemberElement, ObjectDecoder> _decoderMap =
      <MemberElement, ObjectDecoder>{};
  Map<Uri, Token> beginTokenMap = <Uri, Token>{};

  ResolvedAstDeserializerPlugin(
      this.parsingContext, this.nativeDataDeserializer);

  bool hasResolvedAst(ExecutableElement element) {
    return getResolvedAst(element) != null;
  }

  ResolvedAst getResolvedAst(ExecutableElement element) {
    if (element.hasResolvedAst) {
      return element.resolvedAst;
    }

    ObjectDecoder decoder = _decoderMap[element.memberContext];
    if (decoder != null) {
      ResolvedAstDeserializer.deserialize(element.memberContext, decoder,
          parsingContext, findToken, nativeDataDeserializer);
      _decoderMap.remove(element);
      assert(invariant(element, element.hasResolvedAst,
          message: "ResolvedAst not computed for $element."));
      return element.resolvedAst;
    }
    return null;
  }

  Token findToken(Uri uri, int offset) {
    Token beginToken = beginTokenMap.putIfAbsent(uri, () {
      Script script = scripts[uri];
      if (script == null) {
        parsingContext.reporter.internalError(NO_LOCATION_SPANNABLE,
            'No source file found for $uri in:\n ${scripts.keys.join('\n ')}');
      }
      if (script.isSynthesized) return null;
      return new Scanner(script.file).tokenize();
    });
    if (beginToken == null) return null;
    return ResolvedAstDeserializer.findTokenInStream(beginToken, offset);
  }

  @override
  void onElement(Element element, ObjectDecoder getDecoder(String tag)) {
    ObjectDecoder decoder = getDecoder(RESOLVED_AST_TAG);
    if (decoder != null) {
      _decoderMap[element] = decoder;
    }
  }
}
