// 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 js_backend.serialization;

import '../common/backend_api.dart' show BackendSerialization;
import '../elements/elements.dart';
import '../elements/resolution_types.dart';
import '../elements/types.dart';
import '../js/js.dart' as js;
import '../native/native.dart';
import '../serialization/keys.dart';
import '../serialization/serialization.dart'
    show DeserializerPlugin, ObjectDecoder, ObjectEncoder, SerializerPlugin;
import '../universe/side_effects.dart';
import 'js_backend.dart';
import 'native_data.dart';

const String _BACKEND_DATA_TAG = 'jsBackendData';
const Key DART_TYPES_RETURNED = const Key('dartTypesReturned');
const Key THIS_TYPES_RETURNED = const Key('thisTypesReturned');
const Key SPECIAL_TYPES_RETURNED = const Key('specialTypesReturned');
const Key DART_TYPES_INSTANTIATED = const Key('dartTypesInstantiated');
const Key THIS_TYPES_INSTANTIATED = const Key('thisTypesInstantiated');
const Key SPECIAL_TYPES_INSTANTIATED = const Key('specialTypesInstantiated');
const Key CODE_TEMPLATE = const Key('codeTemplate');
const Key SIDE_EFFECTS = const Key('sideEffects');
const Key THROW_BEHAVIOR = const Key('throwBehavior');
const Key IS_ALLOCATION = const Key('isAllocation');
const Key USE_GVN = const Key('useGvn');

class JavaScriptBackendSerialization implements BackendSerialization {
  final JavaScriptBackendSerializer serializer;
  final JavaScriptBackendDeserializer deserializer;

  JavaScriptBackendSerialization(JavaScriptBackend backend)
      : serializer = new JavaScriptBackendSerializer(backend),
        deserializer = new JavaScriptBackendDeserializer(backend);
}

const Key JS_INTEROP_LIBRARY_NAME = const Key('jsInteropLibraryName');
const Key JS_INTEROP_CLASS_NAME = const Key('jsInteropClassName');
const Key JS_INTEROP_MEMBER_NAME = const Key('jsInteropMemberName');
const Key NATIVE_MEMBER_NAME = const Key('nativeMemberName');
const Key NATIVE_CLASS_TAG_INFO = const Key('nativeClassTagInfo');
const Key NATIVE_METHOD_BEHAVIOR = const Key('nativeMethodBehavior');
const Key NATIVE_FIELD_LOAD_BEHAVIOR = const Key('nativeFieldLoadBehavior');
const Key NATIVE_FIELD_STORE_BEHAVIOR = const Key('nativeFieldStoreBehavior');

class JavaScriptBackendSerializer implements SerializerPlugin {
  final JavaScriptBackend _backend;

  JavaScriptBackendSerializer(this._backend);

  NativeBasicDataImpl get nativeBasicData => _backend.nativeBasicData;
  NativeDataImpl get nativeData => _backend.nativeData;

  @override
  void onElement(Element element, ObjectEncoder createEncoder(String tag)) {
    ObjectEncoder encoder;
    ObjectEncoder getEncoder() {
      return encoder ??= createEncoder(_BACKEND_DATA_TAG);
    }

    String jsInteropLibraryName = nativeData.jsInteropLibraryNames[element];
    if (jsInteropLibraryName != null) {
      getEncoder().setString(JS_INTEROP_LIBRARY_NAME, jsInteropLibraryName);
    }
    String jsInteropClassName = nativeData.jsInteropClassNames[element];
    if (jsInteropClassName != null) {
      getEncoder().setString(JS_INTEROP_CLASS_NAME, jsInteropClassName);
    }
    String jsInteropMemberName = nativeData.jsInteropMemberNames[element];
    if (jsInteropMemberName != null) {
      getEncoder().setString(JS_INTEROP_MEMBER_NAME, jsInteropMemberName);
    }
    String nativeMemberName = nativeData.nativeMemberName[element];
    if (nativeMemberName != null) {
      getEncoder().setString(NATIVE_MEMBER_NAME, nativeMemberName);
    }
    NativeClassTag nativeClassTagInfo =
        nativeBasicData.nativeClassTagInfo[element];
    if (nativeClassTagInfo != null) {
      getEncoder().setString(NATIVE_CLASS_TAG_INFO, nativeClassTagInfo.text);
    }
    NativeBehavior nativeMethodBehavior =
        nativeData.nativeMethodBehavior[element];
    if (nativeMethodBehavior != null) {
      NativeBehaviorSerialization.serializeNativeBehavior(nativeMethodBehavior,
          getEncoder().createObject(NATIVE_METHOD_BEHAVIOR));
    }
    NativeBehavior nativeFieldLoadBehavior =
        nativeData.nativeFieldLoadBehavior[element];
    if (nativeFieldLoadBehavior != null) {
      NativeBehaviorSerialization.serializeNativeBehavior(
          nativeFieldLoadBehavior,
          getEncoder().createObject(NATIVE_FIELD_LOAD_BEHAVIOR));
    }
    NativeBehavior nativeFieldStoreBehavior =
        nativeData.nativeFieldStoreBehavior[element];
    if (nativeFieldStoreBehavior != null) {
      NativeBehaviorSerialization.serializeNativeBehavior(
          nativeFieldStoreBehavior,
          getEncoder().createObject(NATIVE_FIELD_STORE_BEHAVIOR));
    }
  }

  @override
  void onData(NativeBehavior behavior, ObjectEncoder encoder) {
    NativeBehaviorSerialization.serializeNativeBehavior(behavior, encoder);
  }
}

class JavaScriptBackendDeserializer implements DeserializerPlugin {
  final JavaScriptBackend _backend;

  JavaScriptBackendDeserializer(this._backend);

  NativeBasicDataBuilderImpl get nativeBasicData =>
      _backend.nativeBasicDataBuilder;
  NativeDataImpl get nativeData => _backend.nativeData;

  @override
  void onElement(Element element, ObjectDecoder getDecoder(String tag)) {
    ObjectDecoder decoder = getDecoder(_BACKEND_DATA_TAG);
    if (decoder != null) {
      if (element is LibraryElement) {
        String jsInteropLibraryName =
            decoder.getString(JS_INTEROP_LIBRARY_NAME, isOptional: true);
        if (jsInteropLibraryName != null) {
          nativeData.jsInteropLibraryNames[element] = jsInteropLibraryName;
        }
      } else if (element is ClassElement) {
        String jsInteropClassName =
            decoder.getString(JS_INTEROP_CLASS_NAME, isOptional: true);
        if (jsInteropClassName != null) {
          nativeData.jsInteropClassNames[element] = jsInteropClassName;
        }
        String nativeClassTagInfo =
            decoder.getString(NATIVE_CLASS_TAG_INFO, isOptional: true);
        if (nativeClassTagInfo != null) {
          nativeBasicData.nativeClassTagInfo[element] =
              new NativeClassTag(nativeClassTagInfo);
        }
      } else if (element is MemberElement) {
        String jsInteropMemberName =
            decoder.getString(JS_INTEROP_MEMBER_NAME, isOptional: true);
        if (jsInteropMemberName != null) {
          nativeData.jsInteropMemberNames[element] = jsInteropMemberName;
        }
        String nativeMemberName =
            decoder.getString(NATIVE_MEMBER_NAME, isOptional: true);
        if (nativeMemberName != null) {
          nativeData.nativeMemberName[element] = nativeMemberName;
        }

        if (element is MethodElement) {
          ObjectDecoder nativeMethodBehavior =
              decoder.getObject(NATIVE_METHOD_BEHAVIOR, isOptional: true);
          if (nativeMethodBehavior != null) {
            nativeData.nativeMethodBehavior[element] =
                NativeBehaviorSerialization
                    .deserializeNativeBehavior(nativeMethodBehavior);
          }
        } else if (element is FieldElement) {
          ObjectDecoder nativeFieldLoadBehavior =
              decoder.getObject(NATIVE_FIELD_LOAD_BEHAVIOR, isOptional: true);
          if (nativeFieldLoadBehavior != null) {
            nativeData.nativeFieldLoadBehavior[element] =
                NativeBehaviorSerialization
                    .deserializeNativeBehavior(nativeFieldLoadBehavior);
          }
          ObjectDecoder nativeFieldStoreBehavior =
              decoder.getObject(NATIVE_FIELD_STORE_BEHAVIOR, isOptional: true);
          if (nativeFieldStoreBehavior != null) {
            nativeData.nativeFieldStoreBehavior[element] =
                NativeBehaviorSerialization
                    .deserializeNativeBehavior(nativeFieldStoreBehavior);
          }
        }
      }
    }
  }

  @override
  NativeBehavior onData(ObjectDecoder decoder) {
    return NativeBehaviorSerialization.deserializeNativeBehavior(decoder);
  }
}

class NativeBehaviorSerialization {
  static const int NORMAL_TYPE = 0;
  static const int THIS_TYPE = 1;
  static const int SPECIAL_TYPE = 2;

  static int getTypeKind(var type) {
    if (type is DartType) {
      // TODO(johnniwinther): Remove this when annotation are no longer resolved
      // to this-types.
      if (type is InterfaceType &&
          type.typeArguments.isNotEmpty &&
          type.typeArguments.first is TypeVariableType) {
        return THIS_TYPE;
      }
      return NORMAL_TYPE;
    }
    return SPECIAL_TYPE;
  }

  /// Returns a list of the non-this-type [ResolutionDartType]s in [types].
  static List<ResolutionDartType> filterDartTypes(List types) {
    return types.where((type) => getTypeKind(type) == NORMAL_TYPE).toList();
  }

  // TODO(johnniwinther): Remove this when annotation are no longer resolved
  // to this-types.
  /// Returns a list of the classes of this-types in [types].
  static List<Element> filterThisTypes(List types) {
    return types
        .where((type) => getTypeKind(type) == THIS_TYPE)
        .map((type) => type.element)
        .toList();
  }

  /// Returns a list of the names of the [SpecialType]s in [types].
  static List<String> filterSpecialTypes(List types) {
    return types
        .where((type) => getTypeKind(type) == SPECIAL_TYPE)
        .map((SpecialType type) => type.name)
        .toList();
  }

  static void serializeNativeBehavior(
      NativeBehavior behavior, ObjectEncoder encoder) {
    encoder.setTypes(
        DART_TYPES_RETURNED, filterDartTypes(behavior.typesReturned));
    encoder.setElements(
        THIS_TYPES_RETURNED, filterThisTypes(behavior.typesReturned));
    encoder.setStrings(
        SPECIAL_TYPES_RETURNED, filterSpecialTypes(behavior.typesReturned));

    encoder.setTypes(
        DART_TYPES_INSTANTIATED, filterDartTypes(behavior.typesInstantiated));
    encoder.setElements(
        THIS_TYPES_INSTANTIATED, filterThisTypes(behavior.typesInstantiated));
    encoder.setStrings(SPECIAL_TYPES_INSTANTIATED,
        filterSpecialTypes(behavior.typesInstantiated));

    if (behavior.codeTemplateText != null) {
      encoder.setString(CODE_TEMPLATE, behavior.codeTemplateText);
    }

    encoder.setInt(SIDE_EFFECTS, behavior.sideEffects.flags);
    encoder.setEnum(THROW_BEHAVIOR, behavior.throwBehavior);
    encoder.setBool(IS_ALLOCATION, behavior.isAllocation);
    encoder.setBool(USE_GVN, behavior.useGvn);
  }

  static NativeBehavior deserializeNativeBehavior(ObjectDecoder decoder) {
    SideEffects sideEffects =
        new SideEffects.fromFlags(decoder.getInt(SIDE_EFFECTS));
    NativeBehavior behavior = new NativeBehavior.internal(sideEffects);

    behavior.typesReturned
        .addAll(decoder.getTypes(DART_TYPES_RETURNED, isOptional: true));
    behavior.typesReturned.addAll(decoder
        .getElements(THIS_TYPES_RETURNED, isOptional: true)
        .map((element) => element.thisType)
        .toList());
    behavior.typesReturned.addAll(decoder
        .getStrings(SPECIAL_TYPES_RETURNED, isOptional: true)
        .map(SpecialType.fromName));

    behavior.typesInstantiated
        .addAll(decoder.getTypes(DART_TYPES_INSTANTIATED, isOptional: true));
    behavior.typesInstantiated.addAll(decoder
        .getElements(THIS_TYPES_INSTANTIATED, isOptional: true)
        .map((element) => element.thisType)
        .toList());
    behavior.typesInstantiated.addAll(decoder
        .getStrings(SPECIAL_TYPES_INSTANTIATED, isOptional: true)
        .map(SpecialType.fromName));

    behavior.codeTemplateText =
        decoder.getString(CODE_TEMPLATE, isOptional: true);
    if (behavior.codeTemplateText != null) {
      behavior.codeTemplate = js.js.parseForeignJS(behavior.codeTemplateText);
    }

    behavior.throwBehavior =
        decoder.getEnum(THROW_BEHAVIOR, NativeThrowBehavior.values);
    behavior.isAllocation = decoder.getBool(IS_ALLOCATION);
    behavior.useGvn = decoder.getBool(USE_GVN);
    return behavior;
  }
}
