/*
 * Copyright 2007 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package java.lang;

import static javaemul.internal.InternalPreconditions.checkNotNull;

import javaemul.internal.JsUtils;
import jsinterop.annotations.JsMethod;

/**
 * Wraps a primitive <code>double</code> as an object.
 */
public final class Double extends Number implements Comparable<Double> {
  public static final double MAX_VALUE = 1.7976931348623157e+308;
  public static final double MIN_VALUE = 4.9e-324;
  public static final double MIN_NORMAL = 2.2250738585072014e-308;
  public static final int MAX_EXPONENT = 1023;
                             // ==Math.getExponent(Double.MAX_VALUE);
  public static final int MIN_EXPONENT = -1022;
                             // ==Math.getExponent(Double.MIN_NORMAL);

  public static final double NaN = 0d / 0d;
  public static final double NEGATIVE_INFINITY = -1d / 0d;
  public static final double POSITIVE_INFINITY = 1d / 0d;
  public static final int SIZE = 64;
  public static final int BYTES = SIZE / Byte.SIZE;
  public static final Class<Double> TYPE = double.class;

  // 2^512, 2^-512
  private static final double POWER_512 = 1.3407807929942597E154;
  private static final double POWER_MINUS_512 = 7.458340731200207E-155;
  // 2^256, 2^-256
  private static final double POWER_256 = 1.157920892373162E77;
  private static final double POWER_MINUS_256 = 8.636168555094445E-78;
  // 2^128, 2^-128
  private static final double POWER_128 = 3.4028236692093846E38;
  private static final double POWER_MINUS_128 = 2.9387358770557188E-39;
  // 2^64, 2^-64
  private static final double POWER_64 = 18446744073709551616.0;
  private static final double POWER_MINUS_64 = 5.421010862427522E-20;
  // 2^52, 2^-52
  private static final double POWER_52 = 4503599627370496.0;
  private static final double POWER_MINUS_52 = 2.220446049250313E-16;
  // 2^32, 2^-32
  private static final double POWER_32 = 4294967296.0;
  private static final double POWER_MINUS_32 = 2.3283064365386963E-10;
  // 2^31
  private static final double POWER_31 = 2147483648.0;
  // 2^20, 2^-20
  private static final double POWER_20 = 1048576.0;
  private static final double POWER_MINUS_20 = 9.5367431640625E-7;
  // 2^16, 2^-16
  private static final double POWER_16 = 65536.0;
  private static final double POWER_MINUS_16 = 0.0000152587890625;
  // 2^8, 2^-8
  private static final double POWER_8 = 256.0;
  private static final double POWER_MINUS_8 = 0.00390625;
  // 2^4, 2^-4
  private static final double POWER_4 = 16.0;
  private static final double POWER_MINUS_4 = 0.0625;
  // 2^2, 2^-2
  private static final double POWER_2 = 4.0;
  private static final double POWER_MINUS_2 = 0.25;
  // 2^1, 2^-1
  private static final double POWER_1 = 2.0;
  private static final double POWER_MINUS_1 = 0.5;
  // 2^-1022 (smallest double non-denorm)
  private static final double POWER_MINUS_1022 = 2.2250738585072014E-308;



  private static class PowersTable {
    private static final double[] powers = {
        POWER_512, POWER_256, POWER_128, POWER_64, POWER_32, POWER_16, POWER_8,
        POWER_4, POWER_2, POWER_1
    };

    private static final double[] invPowers = {
        POWER_MINUS_512, POWER_MINUS_256, POWER_MINUS_128, POWER_MINUS_64,
        POWER_MINUS_32, POWER_MINUS_16, POWER_MINUS_8, POWER_MINUS_4, POWER_MINUS_2,
        POWER_MINUS_1
    };
  }

  public static int compare(double x, double y) {
    if (x < y) {
      return -1;
    }
    if (x > y) {
      return 1;
    }
    if (x == y) {
      return x == 0 ? Double.compare(1 / x, 1 / y) : 0;
    }

    if (isNaN(x)) {
      if (isNaN(y)) {
        return 0;
      } else {
        return 1;
      }
    } else {
      return -1;
    }
  }

  public static long doubleToLongBits(double value) {
    if (isNaN(value)) {
      return 0x7ff8000000000000L;
    }

    boolean negative = false;
    if (value == 0.0) {
      if (1.0 / value == NEGATIVE_INFINITY) {
        return 0x8000000000000000L; // -0.0
      } else {
        return 0x0L;
      }
    }
    if (value < 0.0) {
      negative = true;
      value = -value;
    }
    if (isInfinite(value)) {
      if (negative) {
        return 0xfff0000000000000L;
      } else {
        return 0x7ff0000000000000L;
      }
    }

    int exp = 0;

    // Scale d by powers of 2 into the range [1.0, 2.0)
    // If the exponent would go below -1023, scale into (0.0, 1.0) instead
    if (value < 1.0) {
      int bit = 512;
      for (int i = 0; i < 10; i++, bit >>= 1) {
        if (value < PowersTable.invPowers[i] && exp - bit >= -1023) {
          value *= PowersTable.powers[i];
          exp -= bit;
        }
      }
      // Force into [1.0, 2.0) range
      if (value < 1.0 && exp - 1 >= -1023) {
        value *= 2.0;
        exp--;
      }
    } else if (value >= 2.0) {
      int bit = 512;
      for (int i = 0; i < 10; i++, bit >>= 1) {
        if (value >= PowersTable.powers[i]) {
          value *= PowersTable.invPowers[i];
          exp += bit;
        }
      }
    }

    if (exp > -1023) {
      // Remove significand of non-denormalized mantissa
      value -= 1.0;
    } else {
      // Insert 0 bit as significand of denormalized mantissa
      value *= 0.5;
    }

    // Extract high 20 bits of mantissa
    long ihi = (long) (value * POWER_20);

    // Extract low 32 bits of mantissa
    value -= ihi * POWER_MINUS_20;

    long ilo = (long) (value * POWER_52);

    // Exponent bits
    ihi |= (exp + 1023) << 20;

    // Sign bit
    if (negative) {
      ihi |= 0x80000000L;
    }

    return (ihi << 32) | ilo;
  }

  public static int hashCode(double d) {
    return (int) d;
  }

  @JsMethod(namespace = "<window>")
  public static native boolean isFinite(double x);

  public static boolean isInfinite(double x) {
    return !isNaN(x) && !isFinite(x);
  }

  @JsMethod(namespace = "<window>")
  public static native boolean isNaN(double x);

  public static double longBitsToDouble(long bits) {
    long ihi = (long) (bits >> 32);
    long ilo = (long) (bits & 0xffffffffL);
    if (ihi < 0) {
      ihi += 0x100000000L;
    }
    if (ilo < 0) {
      ilo += 0x100000000L;
    }

    boolean negative = (ihi & 0x80000000) != 0;
    int exp = (int) ((ihi >> 20) & 0x7ff);
    ihi &= 0xfffff; // remove sign bit and exponent

    if (exp == 0x0) {
      double d = (ihi * POWER_MINUS_20) + (ilo * POWER_MINUS_52);
      d *= POWER_MINUS_1022;
      return negative ? (d == 0.0 ? -0.0 : -d) : d;
    } else if (exp == 0x7ff) {
      if (ihi == 0 && ilo == 0) {
        return negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
      } else {
        return Double.NaN;
      }
    }

    // Normalize exponent
    exp -= 1023;

    double d = 1.0 + (ihi * POWER_MINUS_20) + (ilo * POWER_MINUS_52);
    if (exp > 0) {
      int bit = 512;
      for (int i = 0; i < 10; i++, bit >>= 1) {
        if (exp >= bit) {
          d *= PowersTable.powers[i];
          exp -= bit;
        }
      }
    } else if (exp < 0) {
      while (exp < 0) {
        int bit = 512;
        for (int i = 0; i < 10; i++, bit >>= 1) {
          if (exp <= -bit) {
            d *= PowersTable.invPowers[i];
            exp += bit;
          }
        }
      }
    }
    return negative ? -d : d;
  }

  public static double max(double a, double b) {
    return Math.max(a, b);
  }

  public static double min(double a, double b) {
    return Math.min(a, b);
  }

  public static double parseDouble(String s) throws NumberFormatException {
    return __parseAndValidateDouble(s);
  }

  public static double sum(double a, double b) {
    return a + b;
  }

  public static String toString(double b) {
    return String.valueOf(b);
  }

  public static Double valueOf(double d) {
    return new Double(d);
  }

  public static Double valueOf(String s) throws NumberFormatException {
    return new Double(s);
  }

  public Double(double value) {
    /*
     * Call to $create(value) must be here so that the method is referenced and not
     * pruned before new Double(value) is replaced by $create(value) by
     * RewriteConstructorCallsForUnboxedTypes.
     */
    $create(value);
  }

  public Double(String s) {
    /*
     * Call to $create(value) must be here so that the method is referenced and not
     * pruned before new Double(value) is replaced by $create(value) by
     * RewriteConstructorCallsForUnboxedTypes.
     */
    $create(s);
  }

  @Override
  public byte byteValue() {
    return (byte) doubleValue();
  }

  @Override
  public int compareTo(Double b) {
    return compare(doubleValue(), b.doubleValue());
  }

  @Override
  public double doubleValue() {
    return JsUtils.unsafeCastToDouble(checkNotNull(this));
  }

  @Override
  public boolean equals(Object o) {
    return checkNotNull(this) == o;
  }

  @Override
  public float floatValue() {
    return (float) doubleValue();
  }

  /**
   * Performance caution: using Double objects as map keys is not recommended.
   * Using double values as keys is generally a bad idea due to difficulty
   * determining exact equality. In addition, there is no efficient JavaScript
   * equivalent of <code>doubleToIntBits</code>. As a result, this method
   * computes a hash code by truncating the whole number portion of the double,
   * which may lead to poor performance for certain value sets if Doubles are
   * used as keys in a {@link java.util.HashMap}.
   */
  @Override
  public int hashCode() {
    return hashCode(doubleValue());
  }

  @Override
  public int intValue() {
    return (int) doubleValue();
  }

  public boolean isInfinite() {
    return isInfinite(doubleValue());
  }

  public boolean isNaN() {
    return isNaN(doubleValue());
  }

  @Override
  public long longValue() {
    return (long) doubleValue();
  }

  @Override
  public short shortValue() {
    return (short) doubleValue();
  }

  @Override
  public String toString() {
    return toString(doubleValue());
  }

  // CHECKSTYLE_OFF: Utility Methods for unboxed Double.
  protected static Double $create(double x) {
    return JsUtils.uncheckedCast(x);
  }

  protected static Double $create(String s) {
    return JsUtils.uncheckedCast(Double.parseDouble(s));
  }

  @JsMethod
  protected static boolean $isInstance(Object instance) {
    return "number".equals(JsUtils.typeOf(instance));
  }
  //CHECKSTYLE_ON: End utility methods
}
