/*
 * 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 java.io.Serializable;

import javaemul.internal.JsUtils;
import javaemul.internal.NativeRegExp;

import jsinterop.annotations.JsMethod;
import jsinterop.annotations.JsType;

/**
 * Abstract base class for numeric wrapper classes.
 */
public abstract class Number implements Serializable {

  /**
   * Stores a regular expression object to verify the format of float values.
   */
  private static NativeRegExp floatRegex;

  // CHECKSTYLE_OFF: A special need to use unusual identifiers to avoid
  // introducing name collisions.

  static class __Decode {
    public final String payload;
    public final int radix;

    public __Decode(int radix, String payload) {
      this.radix = radix;
      this.payload = payload;
    }
  }

  /**
   * Use nested class to avoid clinit on outer.
   */
  static class __ParseLong {
    /**
     * The number of digits (excluding minus sign and leading zeros) to process
     * at a time.  The largest value expressible in maxDigits digits as well as
     * the factor radix^maxDigits must be strictly less than 2^31.
     */
    private static final int[] maxDigitsForRadix = {-1, -1, // unused
      30, // base 2
      19, // base 3
      15, // base 4
      13, // base 5
      11, 11, // base 6-7
      10, // base 8
      9, 9, // base 9-10
      8, 8, 8, 8, // base 11-14
      7, 7, 7, 7, 7, 7, 7, // base 15-21
      6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, // base 22-35
      5 // base 36
    };

    /**
     * A table of values radix*maxDigitsForRadix[radix].
     */
    private static final int[] maxDigitsRadixPower = new int[37];

    /**
     * The largest number of digits (excluding minus sign and leading zeros) that
     * can fit into a long for a given radix between 2 and 36, inclusive.
     */
    private static final int[] maxLengthForRadix = {-1, -1, // unused
      63, // base 2
      40, // base 3
      32, // base 4
      28, // base 5
      25, // base 6
      23, // base 7
      21, // base 8
      20, // base 9
      19, // base 10
      19, // base 11
      18, // base 12
      18, // base 13
      17, // base 14
      17, // base 15
      16, // base 16
      16, // base 17
      16, // base 18
      15, // base 19
      15, // base 20
      15, // base 21
      15, // base 22
      14, // base 23
      14, // base 24
      14, // base 25
      14, // base 26
      14, // base 27
      14, // base 28
      13, // base 29
      13, // base 30
      13, // base 31
      13, // base 32
      13, // base 33
      13, // base 34
      13, // base 35
      13  // base 36
    };

    /**
     * A table of floor(MAX_VALUE / maxDigitsRadixPower).
     */
    private static final long[] maxValueForRadix = new long[37];

    static {
      for (int i = 2; i <= 36; i++) {
        maxDigitsRadixPower[i] = (int) Math.pow(i, maxDigitsForRadix[i]);
        maxValueForRadix[i] = Long.MAX_VALUE / maxDigitsRadixPower[i];
      }
    }
  }

  @JsType(isNative = true, name = "Number$impl", namespace = "java.lang")
  private static class JavaLangNumber { }

  @JsMethod
  private static boolean $isInstance(Object instance) {
    return "number".equals(JsUtils.typeOf(instance)) || instance instanceof JavaLangNumber;
  }

  /**
   * @skip
   *
   * This function will determine the radix that the string is expressed in
   * based on the parsing rules defined in the Javadocs for Integer.decode() and
   * invoke __parseAndValidateInt.
   */
  protected static int __decodeAndValidateInt(String s, int lowerBound,
      int upperBound) throws NumberFormatException {
    __Decode decode = __decodeNumberString(s);
    return __parseAndValidateInt(decode.payload, decode.radix, lowerBound,
        upperBound);
  }

  protected static __Decode __decodeNumberString(String s) {
    final boolean negative;
    if (s.startsWith("-")) {
      negative = true;
      s = s.substring(1);
    } else {
      negative = false;
      if (s.startsWith("+")) {
        s = s.substring(1);
      }
    }

    final int radix;
    if (s.startsWith("0x") || s.startsWith("0X")) {
      s = s.substring(2);
      radix = 16;
    } else if (s.startsWith("#")) {
      s = s.substring(1);
      radix = 16;
    } else if (s.startsWith("0")) {
      radix = 8;
    } else {
      radix = 10;
    }

    if (negative) {
      s = "-" + s;
    }
    return new __Decode(radix, s);
  }

  /**
   * @skip
   *
   * This function contains common logic for parsing a String as a floating-
   * point number and validating the range.
   */
  protected static double __parseAndValidateDouble(String s) throws NumberFormatException {
    if (!__isValidDouble(s)) {
      throw NumberFormatException.forInputString(s);
    }
    return parseFloat(s);
  }

  @JsMethod(namespace = "<window>")
  private static native double parseFloat(String str);

  /**
   * @skip
   *
   * This function contains common logic for parsing a String in a given radix
   * and validating the result.
   */
  protected static int __parseAndValidateInt(String s, int radix, int lowerBound, int upperBound)
      throws NumberFormatException {
    if (s == null) {
      throw NumberFormatException.forNullInputString();
    }
    if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
      throw NumberFormatException.forRadix(radix);
    }

    int length = s.length();
    int startIndex = (length > 0) && (s.charAt(0) == '-' || s.charAt(0) == '+') ? 1 : 0;

    for (int i = startIndex; i < length; i++) {
      if (Character.digit(s.charAt(i), radix) == -1) {
        throw NumberFormatException.forInputString(s);
      }
    }

    int toReturn = JsUtils.parseInt(s, radix);
    // isTooLow is separated into its own variable to avoid a bug in BlackBerry OS 7. See
    // https://code.google.com/p/google-web-toolkit/issues/detail?id=7291.
    boolean isTooLow = toReturn < lowerBound;
    if (Double.isNaN(toReturn)) {
      throw NumberFormatException.forInputString(s);
    } else if (isTooLow || toReturn > upperBound) {
      throw NumberFormatException.forInputString(s);
    }

    return toReturn;
  }

  /**
   * @skip
   *
   * This function contains common logic for parsing a String in a given radix
   * and validating the result.
   */
  protected static long __parseAndValidateLong(String s, int radix) throws NumberFormatException {
    if (s == null) {
      throw NumberFormatException.forNullInputString();
    }
    if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
      throw NumberFormatException.forRadix(radix);
    }

    final String orig = s;

    int length = s.length();
    boolean negative = false;
    if (length > 0) {
      char c = s.charAt(0);
      if (c == '-' || c == '+') {
        s = s.substring(1);
        length--;
        negative = (c == '-');
      }
    }
    if (length == 0) {
      throw NumberFormatException.forInputString(orig);
    }

    // Strip leading zeros
    while (s.length() > 0 && s.charAt(0) == '0') {
      s = s.substring(1);
      length--;
    }

    // Immediately eject numbers that are too long -- this avoids more complex
    // overflow handling below
    if (length > __ParseLong.maxLengthForRadix[radix]) {
      throw NumberFormatException.forInputString(orig);
    }

    // Validate the digits
    for (int i = 0; i < length; i++) {
      if (Character.digit(s.charAt(i), radix) == -1) {
        throw NumberFormatException.forInputString(orig);
      }
    }

    long toReturn = 0;
    int maxDigits = __ParseLong.maxDigitsForRadix[radix];
    long radixPower = __ParseLong.maxDigitsRadixPower[radix];
    long minValue = -__ParseLong.maxValueForRadix[radix];

    boolean firstTime = true;
    int head = length % maxDigits;
    if (head > 0) {
      // accumulate negative numbers, as -Long.MAX_VALUE == Long.MIN_VALUE + 1
      // (in other words, -Long.MIN_VALUE overflows, see issue 7308)
      toReturn = - JsUtils.parseInt(s.substring(0, head), radix);
      s = s.substring(head);
      length -= head;
      firstTime = false;
    }

    while (length >= maxDigits) {
      head = JsUtils.parseInt(s.substring(0, maxDigits), radix);
      s = s.substring(maxDigits);
      length -= maxDigits;
      if (!firstTime) {
        // Check whether multiplying by radixPower will overflow
        if (toReturn < minValue) {
          throw NumberFormatException.forInputString(orig);
        }
        toReturn *= radixPower;
      } else {
        firstTime = false;
      }
      toReturn -= head;
    }

    // A positive value means we overflowed Long.MIN_VALUE
    if (toReturn > 0) {
      throw NumberFormatException.forInputString(orig);
    }

    if (!negative) {
      toReturn = -toReturn;
      // A negative value means we overflowed Long.MAX_VALUE
      if (toReturn < 0) {
        throw NumberFormatException.forInputString(orig);
      }
    }
    return toReturn;
  }

  /**
   * @skip
   *
   * @param str
   * @return {@code true} if the string matches the float format, {@code false} otherwise
   */
  private static boolean __isValidDouble(String str) {
    if (floatRegex == null) {
      floatRegex =
          new NativeRegExp(
              "^\\s*[+-]?(NaN|Infinity|((\\d+\\.?\\d*)|(\\.\\d+))([eE][+-]?\\d+)?[dDfF]?)\\s*$");
    }
    return floatRegex.test(str);
  }

  // CHECKSTYLE_ON

  public byte byteValue() {
    return (byte) intValue();
  }

  public abstract double doubleValue();

  public abstract float floatValue();

  public abstract int intValue();

  public abstract long longValue();

  public short shortValue() {
    return (short) intValue();
  }
}
