/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * 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.math;

import org.apache.harmony.math.internal.nls.Messages;
import org.openssl.NativeBN;

import java.util.Random;

/*
 * In contrast to BigIntegers this class doesn't fake two's complement representation.
 * Any Bit-Operations, including Shifting, solely regard the unsigned magnitude.
 * Moreover BigInt objects are mutable and offer efficient in-place-operations.
 */

class BigInt
// extends Number
// implements Comparable<BigInt>,
//        Serializable
{

    class Context {
        int bnctx;
        Context() {
            bnctx = NativeBN.BN_CTX_new();
        }
    }
    static BigInt dummy;
    static Context defaultContext;

    static {
        dummy = new BigInt();
        defaultContext = dummy.new Context();
    }

    static int getCtx (Context t) {
        return (t != null) ? t.bnctx : defaultContext.bnctx;
    }

    /** This is the serialVersionUID used by the sun implementation */
    private static final long serialVersionUID = -8287574255936472291L;

    /* Fields used for the internal representation. */
    transient int bignum = 0;


    public void dispose() {
        if (this.bignum != 0) {
            NativeBN.BN_free(this.bignum);
            this.bignum = 0;
        }
    }

    @Override
    protected void finalize() {
        dispose();
    }

    @Override
    public String toString() {
        return this.decString();
    }

    public int getNativeBIGNUM() {
        return this.bignum;
    }

    public static int consumeErrors(StringBuilder sb) {
        int cnt = 0;
        int e, reason;
        boolean first = true;
        while ((e = NativeBN.ERR_get_error()) != 0) {
            reason = e & 255;
            if (reason == 103) {
                // math.17=BigInteger divide by zero
                throw new ArithmeticException(Messages.getString("math.17")); //$NON-NLS-1$
            }
            if (reason == 108) {
                // math.19=BigInteger not invertible.
                throw new ArithmeticException(Messages.getString("math.19")); //$NON-NLS-1$
            }
            if (reason == 65) {
                throw new OutOfMemoryError();
            }
            if (!first) { sb.append(" *** "); first = false; }
            sb.append(e).append(": ");
            String s = NativeBN.ERR_error_string(e);
            sb.append(s);
            cnt++;
        }
        return cnt;
    }

    private static void Check(boolean success) {
        if (!success) {
            StringBuilder sb = new StringBuilder("(openssl)ERR: ");
            int cnt = consumeErrors(sb);
            if (cnt > 0)
                throw new ArithmeticException(sb.toString());
        }
    }


    private void makeValid() {
        if (this.bignum == 0) {
            this.bignum = NativeBN.BN_new();
            Check(this.bignum != 0);
        }
    }

    private static BigInt newBigInt() {
        BigInt bi = new BigInt();
        bi.bignum = NativeBN.BN_new();
        Check(bi.bignum != 0);
        return bi;
    }


    public static int cmp(BigInt a, BigInt b) {
        return NativeBN.BN_cmp(a.bignum, b.bignum);
    }


    public void putCopy(BigInt from) {
        this.makeValid();
        Check(NativeBN.BN_copy(this.bignum, from.bignum));
    }

    public BigInt copy() {
        BigInt bi = new BigInt();
        bi.putCopy(this);
        return bi;
    }


    public void putLongInt(long val) {
        this.makeValid();
        Check(NativeBN.putLongInt(this.bignum, val));
    }

    public void putULongInt(long val, boolean neg) {
        this.makeValid();
        Check(NativeBN.putULongInt(this.bignum, val, neg));
    }

    public void putDecString(String str) {
        if (str == null) throw new NullPointerException();
        if (str.length() == 0) {
            // math.12=Zero length BigInteger
            throw new NumberFormatException(Messages.getString("math.12")); //$NON-NLS-1$
        }
        this.makeValid();
        int usedLen = NativeBN.BN_dec2bn(this.bignum, str);
        Check((usedLen > 0));
        if (usedLen < str.length()) {
            throw new NumberFormatException(str);
        }
    }

    public void putHexString(String str) {
        if (str == null) throw new NullPointerException();
        if (str.length() == 0) {
            // math.12=Zero length BigInteger
            throw new NumberFormatException(Messages.getString("math.12")); //$NON-NLS-1$
        }
        this.makeValid();
        int usedLen = NativeBN.BN_hex2bn(this.bignum, str);
        Check((usedLen > 0));
        if (usedLen < str.length()) {
            throw new NumberFormatException(str);
        }
    }

    public void putBigEndian(byte[] a, boolean neg) {
        this.makeValid();
        Check(NativeBN.BN_bin2bn(a, a.length, neg, this.bignum));
    }

    public void putLittleEndianInts(int[] a, boolean neg) {
        this.makeValid();
        Check(NativeBN.litEndInts2bn(a, a.length, neg, this.bignum));
    }

    public void putBigEndianTwosComplement(byte[] a) {
        this.makeValid();
        Check(NativeBN.twosComp2bn(a, a.length, this.bignum));
    }


    public long longInt() {
        return NativeBN.longInt(this.bignum);
    }

    public String decString() {
        String str = NativeBN.BN_bn2dec(this.bignum);
        return str;
    }

    public String hexString() {
        String str = NativeBN.BN_bn2hex(this.bignum);
        return str;
    }

    public byte[] bigEndianMagnitude() {
        byte[] a = NativeBN.BN_bn2bin(this.bignum, null);
        return a;
    }

    public int[] littleEndianIntsMagnitude() {
        int[] a = NativeBN.bn2litEndInts(this.bignum, null);
        return a;
    }

    public int sign() {
        return NativeBN.sign(this.bignum);
    }

    public void setSign(int val) {
        if (val > 0) NativeBN.BN_set_negative(this.bignum, 0);
        else if (val < 0) NativeBN.BN_set_negative(this.bignum, 1);
    }


    public boolean twosCompFitsIntoBytes(int byteCnt) {
        return NativeBN.twosCompFitsIntoBytes(this.bignum, byteCnt);
    }

    public int bitLength() {
        return NativeBN.bitLength(this.bignum);
    }

    public boolean isBitSet(int n) {
        return NativeBN.BN_is_bit_set(this.bignum, n);
    }

    public void modifyBit(int n, int op) {
        // op: 0 = reset; 1 = set; -1 = flip
        Check(NativeBN.modifyBit(this.bignum, n, op));
    }


    // n > 0: shift left (multiply)
    public static BigInt shift(BigInt a, int n) {
        BigInt r = newBigInt();
        Check(NativeBN.BN_lshift(r.bignum, a.bignum, n));
        return r;
    }

    public void shift(int n) {
        Check(NativeBN.BN_lshift(this.bignum, this.bignum, n));
    }

    public void addPositiveInt(int w) {
        Check(NativeBN.BN_add_word(this.bignum, w));
    }

    public void subtractPositiveInt(int w) {
        Check(NativeBN.BN_sub_word(this.bignum, w));
    }

    public void multiplyByPositiveInt(int w) {
        Check(NativeBN.BN_mul_word(this.bignum, w));
    }

    public int divideByPositiveInt(int w) {
        int rem = NativeBN.BN_div_word(this.bignum, w);
        Check(rem != -1);
        return rem;
    }

    public static int remainderByPositiveInt(BigInt a, int w) {
        int rem = NativeBN.BN_mod_word(a.bignum, w);
        Check(rem != -1);
        return rem;
    }

    public static BigInt addition(BigInt a, BigInt b) {
        BigInt r = newBigInt();
        Check(NativeBN.BN_add(r.bignum, a.bignum, b.bignum));
        return r;
    }

    public void add(BigInt a) {
        Check(NativeBN.BN_add(this.bignum, this.bignum, a.bignum));
    }

    public static BigInt subtraction(BigInt a, BigInt b) {
        BigInt r = newBigInt();
        Check(NativeBN.BN_sub(r.bignum, a.bignum, b.bignum));
        return r;
    }


    public static BigInt gcd(BigInt a, BigInt b, Context t) {
        BigInt r = newBigInt();
        Check(NativeBN.BN_gcd(r.bignum, a.bignum, b.bignum, getCtx(t)));
        return r;
    }

    public static BigInt product(BigInt a, BigInt b, Context t) {
        BigInt r = newBigInt();
        Check(NativeBN.BN_mul(r.bignum, a.bignum, b.bignum, getCtx(t)));
        return r;
    }

    public void multiplyBy(BigInt a, Context t) {
        Check(NativeBN.BN_mul(this.bignum, this.bignum, a.bignum, getCtx(t)));
    }

    public static BigInt bigExp(BigInt a, BigInt p, Context t) {
        // Sign of p is ignored!
        BigInt r = newBigInt();
        Check(NativeBN.BN_exp(r.bignum, a.bignum, p.bignum, getCtx(t)));
        return r;
    }

    public static BigInt exp(BigInt a, int p, Context t) {
        // Sign of p is ignored!
        BigInt power = new BigInt();
        power.putLongInt(p);
        return bigExp(a, power, t);
        // OPTIONAL:
//      public int BN_sqr(BigInteger r, BigInteger a, BN_CTX ctx);
      // int BN_sqr(BIGNUM *r, const BIGNUM *a,BN_CTX *ctx);
    }

    public static void division(BigInt dividend, BigInt divisor, Context t,
            BigInt quotient, BigInt remainder) {
        int quot, rem;
        if (quotient != null) {
            quotient.makeValid();
            quot = quotient.bignum;
        }
        else quot = 0;
        if (remainder != null) {
            remainder.makeValid();
            rem = remainder.bignum;
        }
        else rem = 0;
        Check(NativeBN.BN_div(quot, rem, dividend.bignum, divisor.bignum, getCtx(t)));
    }

    public static BigInt modulus(BigInt a, BigInt m, Context t) {
        // Sign of p is ignored! ?
        BigInt r = newBigInt();
        Check(NativeBN.BN_nnmod(r.bignum, a.bignum, m.bignum, getCtx(t)));
        return r;
    }

    public static BigInt modExp(BigInt a, BigInt p, BigInt m, Context t) {
        // Sign of p is ignored!
        BigInt r = newBigInt();
        Check(NativeBN.BN_mod_exp(r.bignum, a.bignum, p.bignum, m.bignum, getCtx(t)));

        // OPTIONAL:
        // int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
        return r;
    }


    public static BigInt modInverse(BigInt a, BigInt m, Context t) {
        BigInt r = newBigInt();
        Check(NativeBN.BN_mod_inverse(r.bignum, a.bignum, m.bignum, getCtx(t)));
        return r;
    }


    public static BigInt generatePrimeDefault(int bitLength, Random rnd, Context t) {
        BigInt r = newBigInt();
        Check(NativeBN.BN_generate_prime_ex(r.bignum, bitLength, false, 0, 0, 0));
        return r;
    }

    public static BigInt generatePrimeSafe(int bitLength, Random rnd, Context t) {
        BigInt r = newBigInt();
        Check(NativeBN.BN_generate_prime_ex(r.bignum, bitLength, true, 0, 0, 0));
        return r;
    }

    public boolean isPrime(int certainty, Random rnd, Context t) {
        return NativeBN.BN_is_prime_ex(bignum, certainty, getCtx(t), 0);
    }
}
