package jp.sourceforge.glad.math.internal;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.math.RoundingMode;

public class NumberContext {

    private Number value;

    private NumberState state;

    private Integer scale;

    private MathContext mathContext;

    public NumberContext() {
        this(0, NullState.getInstance());
    }

    public NumberContext(int value) {
        this(value, IntState.getInstance());
    }

    public NumberContext(long value) {
        this(value, LongState.getInstance());
    }

    public NumberContext(BigInteger value) {
        this(value, BigIntegerState.getInstance());
    }

    public NumberContext(BigDecimal value) {
        this(value, BigDecimalState.getInstance());
    }

    NumberContext(Number value, NumberState state) {
        this(value, state, null, MathContext.UNLIMITED);
    }

    NumberContext(
            Number value, NumberState state,
            Integer scale, MathContext mathContext) {
        this.value = value;
        this.state = state;
        this.scale = scale;
        this.mathContext = mathContext;
    }

    public Number getValue() {
        return value;
    }

    public byte byteValue() {
        return value.byteValue();
    }

    public short shortValue() {
        return value.shortValue();
    }

    public int intValue() {
        return value.intValue();
    }

    public long longValue() {
        return value.longValue();
    }

    public float floatValue() {
        return value.floatValue();
    }

    public double doubleValue() {
        return value.doubleValue();
    }

    public BigInteger toBigInteger() {
        return state.toBigInteger(this);
    }

    public BigDecimal toBigDecimal() {
        return state.toBigDecimal(this);
    }

    public void setValue(int value) {
        set(value, IntState.getInstance());
    }

    public void setValue(long value) {
        set(value, LongState.getInstance());
    }

    public void setValue(BigInteger value) {
        set(value, BigIntegerState.getInstance());
    }

    public void setValue(BigDecimal value) {
        set(value, BigDecimalState.getInstance());
    }

    public NumberState getState() {
        return state;
    }

    void set(Number value, NumberState state) {
        this.value = value;
        this.state = state;
    }

    public Integer getScale() {
        return scale;
    }

    void setScale(Integer scale) {
        this.scale = scale;
    }

    public MathContext getMathContext() {
        return mathContext;
    }

    void setMathContext(MathContext mathContext) {
        this.mathContext = mathContext;
    }

    public int getPrecision() {
        return mathContext.getPrecision();
    }

    public RoundingMode getRoundingMode() {
        return mathContext.getRoundingMode();
    }

    public String toString() {
        return state.toString(this);
    }

}
