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

// @dart=2.9

@JS()
library native_version_javascript;

import 'package:js/js.dart';
import 'native_version.dart';

const NativeBigIntMethods nativeBigInt = _Methods();

@JS('eval')
external Object _eval(String s);

@JS('bigint_parse')
external Object _parse(String s);

@JS('bigint_toString')
external String _toStringMethod(Object o);

@JS('bigint_bitLength')
external int _bitLength(Object o);

@JS('bigint_isEven')
external bool _isEven(Object o);

@JS('bigint_add')
external Object _add(Object left, Object right);

@JS('bigint_shiftLeft')
external Object _shiftLeft(Object o, Object i);

@JS('bigint_shiftRight')
external Object _shiftRight(Object o, Object i);

@JS('bigint_subtract')
external Object _subtract(Object left, Object right);

@JS('bigint_fromInt')
external Object _fromInt(int i);

class _Methods implements NativeBigIntMethods {
  static bool _initialized = false;
  static bool _enabled = false;

  const _Methods();

  @override
  bool get enabled {
    if (!_initialized) {
      _initialize();
    }
    return _enabled;
  }

  void _initialize() {
    _initialized = true;
    try {
      _setup();
      _enabled = true;
    } catch (e) {
      // We get here if the JavaScript implementation does not have BigInt (or
      // run in a stand-alone JavaScript implementation without the right
      // 'preamble').
      //
      // Print so we can see what failed.
      print(e);
    }
  }

  @override
  Object parse(String string) => _parse(string);

  @override
  String toStringMethod(Object value) => _toStringMethod(value);

  @override
  Object fromInt(int i) => _fromInt(i);

  @override
  Object get one => _one;

  @override
  Object get eight => _eight;

  @override
  int bitLength(Object value) => _bitLength(value);

  @override
  bool isEven(Object value) => _isEven(value);

  @override
  Object add(Object left, Object right) => _add(left, right);

  @override
  Object shiftLeft(Object value, Object count) => _shiftLeft(value, count);

  @override
  Object shiftRight(Object value, Object count) => _shiftRight(value, count);

  @override
  Object subtract(Object left, Object right) => _subtract(left, right);
}

void _setup() {
  _one = _eval('1n'); // Throws if JavaScript does not have BigInt.
  _eight = _eval('8n');

  _eval('self.bigint_parse = function parse(s) { return BigInt(s); }');
  _eval('self.bigint_toString = function toString(b) { return b.toString(); }');
  _eval('self.bigint_add = function add(a, b) { return a + b; }');
  _eval('self.bigint_shiftLeft = function shl(v, i) { return v << i; }');
  _eval('self.bigint_shiftRight = function shr(v, i) { return v >> i; }');
  _eval('self.bigint_subtract = function subtract(a, b) { return a - b; }');
  _eval('self.bigint_fromInt = function fromInt(i) { return BigInt(i); }');

  _eval(
    'self.bigint_bitLength = function bitLength(b) {'
    'return b == 0 ? 0 : (b < 0 ? ~b : b).toString(2).length;'
    '}',
  );
  _eval('self.bigint_isEven = function isEven(b) { return (b & 1n) == 0n; }');
}

// `dynamic` to allow null initialization pre- and post- NNBD.
dynamic _one;
dynamic _eight;
