// Copyright (c) 2017, 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 'package:kernel/core_types.dart';
import 'package:kernel/kernel.dart';
import 'package:kernel/library_index.dart';
import 'package:kernel/type_environment.dart';

/// An abstraction of the JS types
abstract class JSType {
  const JSType();

  /// True if this type is built-in to JS, and we use the values unwrapped.
  /// For these types we generate a calling convention via static
  /// "extension methods". This allows types to be extended without adding
  /// extensions directly on the prototype.
  bool get isPrimitive;

  /// Is this type known to be definitively primitive
  /// (using the JS notion of primitive)
  bool get isPrimitiveInJS;

  /// Can a non-null element of this type potentially be interpreted
  /// as false in JS.
  bool get isFalsey;

  static const jsBoolean = const JSBoolean();
  static const jsNumber = const JSNumber();
  static const jsNull = const JSNull();
  static const jsObject = const JSObject();
  static const jsString = const JSString();
  static const jsUnknown = const JSUnknown();
}

/// Inhabited by booleans (including JSBool), null, and undefined
class JSBoolean extends JSType {
  const JSBoolean();
  bool get isPrimitive => true;
  bool get isPrimitiveInJS => true;
  bool get isFalsey => true;
}

/// Inhabited by numbers, null, and undefined
/// In practice, this is 4 types: num, int, double, and _interceptors.JSNumber.
///
/// _interceptors.JSNumber is the type that actually "implements" all numbers,
/// hence it's a subtype of int and double (and num).
/// It's defined in our "dart:_interceptors".
class JSNumber extends JSType {
  const JSNumber();
  bool get isPrimitive => true;
  bool get isPrimitiveInJS => true;
  bool get isFalsey => true;
}

/// Inhabited by null and undefined
class JSNull extends JSType {
  const JSNull();
  bool get isPrimitive => false;
  bool get isPrimitiveInJS => false;
  bool get isFalsey => true;
}

/// Inhabited by objects, null, and undefined
class JSObject extends JSType {
  const JSObject();
  bool get isPrimitive => false;
  bool get isPrimitiveInJS => false;
  bool get isFalsey => false;
}

/// Inhabited by strings (including JSString), null, and undefined
class JSString extends JSType {
  const JSString();
  bool get isPrimitive => true;
  bool get isPrimitiveInJS => false;
  bool get isFalsey => true;
}

/// Inhabitance not statically known
class JSUnknown extends JSType {
  const JSUnknown();
  bool get isPrimitive => false;
  bool get isPrimitiveInJS => false;
  bool get isFalsey => true;
}

class JSTypeRep {
  final TypeEnvironment types;
  final CoreTypes coreTypes;
  final LibraryIndex sdk;

  final Class _jsBool;
  final Class _jsNumber;

  final Class _jsString;
  JSTypeRep(this.types, this.sdk)
      : coreTypes = types.coreTypes,
        _jsBool = sdk.getClass('dart:_interceptors', 'JSBool'),
        _jsNumber = sdk.getClass('dart:_interceptors', 'JSNumber'),
        _jsString = sdk.getClass('dart:_interceptors', 'JSString');

  JSType typeFor(DartType type) {
    while (type is TypeParameterType) {
      type = (type as TypeParameterType).parameter.bound;
    }
    if (type == null) return JSType.jsUnknown;
    // Note that this should be changed if Dart gets non-nullable types
    if (type == const BottomType()) return JSType.jsNull;

    if (type is InterfaceType) {
      var c = type.classNode;
      if (c == coreTypes.nullClass) return JSType.jsNull;
      if (c == coreTypes.numClass ||
          c == coreTypes.intClass ||
          c == coreTypes.doubleClass) {
        return JSType.jsNumber;
      }
      if (c == coreTypes.boolClass) return JSType.jsBoolean;
      if (c == coreTypes.stringClass) return JSType.jsString;
      if (c == coreTypes.objectClass) return JSType.jsUnknown;
      if (c == coreTypes.futureOrClass) {
        var argumentRep = typeFor(type.typeArguments[0]);
        if (argumentRep is JSObject || argumentRep is JSNull) {
          return JSType.jsObject;
        }
        return JSType.jsUnknown;
      }
    }
    if (type == const DynamicType() || type == const VoidType()) {
      return JSType.jsUnknown;
    }
    return JSType.jsObject;
  }

  /// Given a Dart type return the known implementation type, if any.
  /// Given `bool`, `String`, or `num`/`int`/`double`,
  /// returns the corresponding class in `dart:_interceptors`:
  /// `JSBool`, `JSString`, and `JSNumber` respectively, otherwise null.
  Class getImplementationClass(DartType t) {
    JSType rep = typeFor(t);
    // Number, String, and Bool are final
    if (rep == JSType.jsNumber) return _jsNumber;
    if (rep == JSType.jsBoolean) return _jsBool;
    if (rep == JSType.jsString) return _jsString;
    return null;
  }

  /// If the type [t] is [int] or [double], or a type parameter
  /// bounded by [int], [double] or [num] returns [num].
  /// Otherwise returns [t].
  DartType canonicalizeNumTypes(DartType t) =>
      isNumber(t) ? coreTypes.nullClass.rawType : t;

  bool isNumber(DartType type) => typeFor(type) is JSNumber;

  /// Is this type known to be represented as Object or Null in JS.
  bool isObjectOrNull(DartType t) {
    var rep = typeFor(t);
    return rep is JSObject || rep is JSNull;
  }

  bool isUnknown(DartType t) => typeFor(t) is JSUnknown;

  bool isPrimitive(DartType t) => typeFor(t).isPrimitive;

  bool isPrimitiveInJS(DartType t) => typeFor(t).isPrimitiveInJS;

  bool binaryOperationIsPrimitive(DartType leftT, DartType rightT) =>
      isPrimitiveInJS(leftT) && isPrimitiveInJS(rightT);

  bool unaryOperationIsPrimitive(DartType t) => isPrimitiveInJS(t);

  /// True if the JS double equals (`==`) comparison on the representation
  /// of these two types could potentially cause a conversion.
  bool equalityMayConvert(DartType t0, DartType t1) => !equalOrNull(t0, t1);

  // Are t0 and t1 known to either be represented by the same type
  // or else one or both of them is represented by Null
  bool equalOrNull(DartType t0, DartType t1) {
    var rep0 = typeFor(t0);
    var rep1 = typeFor(t1);
    if (rep0 is JSNull || rep1 is JSNull) return true;
    return rep0 == rep1 && rep0 is! JSUnknown;
  }
}
