package jp.sourceforge.glad.math.internal;

import java.math.BigDecimal;
import java.math.BigInteger;

public class BigIntegerState implements NumberState {

    static BigIntegerState getInstance() {
        return instance;
    }

    void init(NumberContext context, BigInteger value) {
        context.set(value, this);
    }

    BigInteger getBigInteger(long value) {
        return BigInteger.valueOf(value);
    }

    public BigInteger toBigInteger(NumberContext context) {
        return (BigInteger) context.getValue();
    }

    public BigDecimal toBigDecimal(NumberContext context) {
        return BigDecimalState.getInstance()
                .toBigDecimal(toBigInteger(context), context.getMathContext());
    }

    public void add(NumberContext context, int value) {
        add(context, getBigInteger(value));
    }

    public void add(NumberContext context, long value) {
        add(context, getBigInteger(value));
    }

    public void add(NumberContext context, BigInteger value) {
        context.set(context.toBigInteger().add(value), this);
    }

    public void add(NumberContext context, BigDecimal value) {
        BigDecimalState.getInstance().add(context, value);
    }

    public void subtract(NumberContext context, int value) {
        subtract(context, getBigInteger(value));
    }

    public void subtract(NumberContext context, long value) {
        subtract(context, getBigInteger(value));
    }

    public void subtract(NumberContext context, BigInteger value) {
        context.set(context.toBigInteger().subtract(value), this);
    }

    public void subtract(NumberContext context, BigDecimal value) {
        BigDecimalState.getInstance().subtract(context, value);
    }

    public void multiply(NumberContext context, int value) {
        multiply(context, getBigInteger(value));
    }

    public void multiply(NumberContext context, long value) {
        multiply(context, getBigInteger(value));
    }

    public void multiply(NumberContext context, BigInteger value) {
        context.set(context.toBigInteger().multiply(value), this);
    }

    public void multiply(NumberContext context, BigDecimal value) {
        BigDecimalState.getInstance().multiply(context, value);
    }

    public void divide(NumberContext context, int value) {
        divide(context, getBigInteger(value));
    }

    public void divide(NumberContext context, long value) {
        divide(context, getBigInteger(value));
    }

    public void divide(NumberContext context, BigInteger value) {
        context.set(context.toBigInteger().divide(value), this);
    }

    public void divide(NumberContext context, BigDecimal value) {
        BigDecimalState.getInstance().divide(context, value);
    }

    public void divideToIntegralValue(
            NumberContext context, BigDecimal value) {
        BigDecimalState.getInstance().divideToIntegralValue(context, value);
    }

    public void remainder(NumberContext context, int value) {
        remainder(context, getBigInteger(value));
    }

    public void remainder(NumberContext context, long value) {
        remainder(context, getBigInteger(value));
    }

    public void remainder(NumberContext context, BigInteger value) {
        context.set(context.toBigInteger().remainder(value), this);
    }

    public void remainder(NumberContext context, BigDecimal value) {
        BigDecimalState.getInstance().remainder(context, value);
    }

    // ---- toString

    public String toString(NumberContext context) {
        return context.toBigInteger().toString();
    }

    static final BigIntegerState instance = new BigIntegerState();

}
