package org.checkerframework.common.value.util;

import org.checkerframework.checker.nullness.qual.Nullable;

public class IntegerMath extends NumberMath<Integer> {
  int number;

  public IntegerMath(int i) {
    number = i;
  }

  @Override
  public Number plus(Number right) {
    if (right instanceof Byte) {
      return number + right.byteValue();
    }
    if (right instanceof Double) {
      return number + right.doubleValue();
    }
    if (right instanceof Float) {
      return number + right.floatValue();
    }
    if (right instanceof Integer) {
      return number + right.intValue();
    }
    if (right instanceof Long) {
      return number + right.longValue();
    }
    if (right instanceof Short) {
      return number + right.shortValue();
    }
    throw new UnsupportedOperationException();
  }

  @Override
  public Number minus(Number right) {
    if (right instanceof Byte) {
      return number - right.byteValue();
    }
    if (right instanceof Double) {
      return number - right.doubleValue();
    }
    if (right instanceof Float) {
      return number - right.floatValue();
    }
    if (right instanceof Integer) {
      return number - right.intValue();
    }
    if (right instanceof Long) {
      return number - right.longValue();
    }
    if (right instanceof Short) {
      return number - right.shortValue();
    }
    throw new UnsupportedOperationException();
  }

  @Override
  public Number times(Number right) {
    if (right instanceof Byte) {
      return number * right.byteValue();
    }
    if (right instanceof Double) {
      return number * right.doubleValue();
    }
    if (right instanceof Float) {
      return number * right.floatValue();
    }
    if (right instanceof Integer) {
      return number * right.intValue();
    }
    if (right instanceof Long) {
      return number * right.longValue();
    }
    if (right instanceof Short) {
      return number * right.shortValue();
    }
    throw new UnsupportedOperationException();
  }

  @Override
  public @Nullable Number divide(Number right) {
    if (isIntegralZero(right)) {
      return null;
    }
    if (right instanceof Byte) {
      return number / right.byteValue();
    }
    if (right instanceof Double) {
      return number / right.doubleValue();
    }
    if (right instanceof Float) {
      return number / right.floatValue();
    }
    if (right instanceof Integer) {
      return number / right.intValue();
    }
    if (right instanceof Long) {
      return number / right.longValue();
    }
    if (right instanceof Short) {
      return number / right.shortValue();
    }
    throw new UnsupportedOperationException();
  }

  @Override
  public @Nullable Number remainder(Number right) {
    if (isIntegralZero(right)) {
      return null;
    }
    if (right instanceof Byte) {
      return number % right.byteValue();
    }
    if (right instanceof Double) {
      return number % right.doubleValue();
    }
    if (right instanceof Float) {
      return number % right.floatValue();
    }
    if (right instanceof Integer) {
      return number % right.intValue();
    }
    if (right instanceof Long) {
      return number % right.longValue();
    }
    if (right instanceof Short) {
      return number % right.shortValue();
    }
    throw new UnsupportedOperationException();
  }

  @Override
  public Number shiftLeft(Number right) {
    if (right instanceof Byte) {
      return number << right.byteValue();
    }
    if (right instanceof Integer) {
      return number << right.intValue();
    }
    if (right instanceof Long) {
      return number << right.longValue();
    }
    if (right instanceof Short) {
      return number << right.shortValue();
    }
    throw new UnsupportedOperationException();
  }

  @Override
  public Number signedShiftRight(Number right) {
    if (right instanceof Byte) {
      return number >> right.byteValue();
    }
    if (right instanceof Integer) {
      return number >> right.intValue();
    }
    if (right instanceof Long) {
      return number >> right.longValue();
    }
    if (right instanceof Short) {
      return number >> right.shortValue();
    }
    throw new UnsupportedOperationException();
  }

  @Override
  public Number unsignedShiftRight(Number right) {
    if (right instanceof Byte) {
      return number >>> right.byteValue();
    }
    if (right instanceof Integer) {
      return number >>> right.intValue();
    }
    if (right instanceof Long) {
      return number >>> right.longValue();
    }
    if (right instanceof Short) {
      return number >>> right.shortValue();
    }
    throw new UnsupportedOperationException();
  }

  @Override
  public Number bitwiseAnd(Number right) {
    if (right instanceof Byte) {
      return number & right.byteValue();
    }
    if (right instanceof Integer) {
      return number & right.intValue();
    }
    if (right instanceof Long) {
      return number & right.longValue();
    }
    if (right instanceof Short) {
      return number & right.shortValue();
    }
    throw new UnsupportedOperationException();
  }

  @Override
  public Number bitwiseXor(Number right) {
    if (right instanceof Byte) {
      return number ^ right.byteValue();
    }
    if (right instanceof Integer) {
      return number ^ right.intValue();
    }
    if (right instanceof Long) {
      return number ^ right.longValue();
    }
    if (right instanceof Short) {
      return number ^ right.shortValue();
    }
    throw new UnsupportedOperationException();
  }

  @Override
  public Number bitwiseOr(Number right) {
    if (right instanceof Byte) {
      return number | right.byteValue();
    }
    if (right instanceof Integer) {
      return number | right.intValue();
    }
    if (right instanceof Long) {
      return number | right.longValue();
    }
    if (right instanceof Short) {
      return number | right.shortValue();
    }
    throw new UnsupportedOperationException();
  }

  @Override
  public Number unaryPlus() {
    return +number;
  }

  @Override
  public Number unaryMinus() {
    return -number;
  }

  @Override
  public Number bitwiseComplement() {
    return ~number;
  }

  @Override
  public Boolean equalTo(Number right) {
    if (right instanceof Byte) {
      return number == right.byteValue();
    }
    if (right instanceof Double) {
      return number == right.doubleValue();
    }
    if (right instanceof Float) {
      return number == right.floatValue();
    }
    if (right instanceof Integer) {
      return number == right.intValue();
    }
    if (right instanceof Long) {
      return number == right.longValue();
    }
    if (right instanceof Short) {
      return number == right.shortValue();
    }
    throw new UnsupportedOperationException();
  }

  @Override
  public Boolean notEqualTo(Number right) {
    if (right instanceof Byte) {
      return number != right.byteValue();
    }
    if (right instanceof Double) {
      return number != right.doubleValue();
    }
    if (right instanceof Float) {
      return number != right.floatValue();
    }
    if (right instanceof Integer) {
      return number != right.intValue();
    }
    if (right instanceof Long) {
      return number != right.longValue();
    }
    if (right instanceof Short) {
      return number != right.shortValue();
    }
    throw new UnsupportedOperationException();
  }

  @Override
  public Boolean greaterThan(Number right) {
    if (right instanceof Byte) {
      return number > right.byteValue();
    }
    if (right instanceof Double) {
      return number > right.doubleValue();
    }
    if (right instanceof Float) {
      return number > right.floatValue();
    }
    if (right instanceof Integer) {
      return number > right.intValue();
    }
    if (right instanceof Long) {
      return number > right.longValue();
    }
    if (right instanceof Short) {
      return number > right.shortValue();
    }
    throw new UnsupportedOperationException();
  }

  @Override
  public Boolean greaterThanEq(Number right) {
    if (right instanceof Byte) {
      return number >= right.byteValue();
    }
    if (right instanceof Double) {
      return number >= right.doubleValue();
    }
    if (right instanceof Float) {
      return number >= right.floatValue();
    }
    if (right instanceof Integer) {
      return number >= right.intValue();
    }
    if (right instanceof Long) {
      return number >= right.longValue();
    }
    if (right instanceof Short) {
      return number >= right.shortValue();
    }
    throw new UnsupportedOperationException();
  }

  @Override
  public Boolean lessThan(Number right) {
    if (right instanceof Byte) {
      return number < right.byteValue();
    }
    if (right instanceof Double) {
      return number < right.doubleValue();
    }
    if (right instanceof Float) {
      return number < right.floatValue();
    }
    if (right instanceof Integer) {
      return number < right.intValue();
    }
    if (right instanceof Long) {
      return number < right.longValue();
    }
    if (right instanceof Short) {
      return number < right.shortValue();
    }
    throw new UnsupportedOperationException();
  }

  @Override
  public Boolean lessThanEq(Number right) {
    if (right instanceof Byte) {
      return number <= right.byteValue();
    }
    if (right instanceof Double) {
      return number <= right.doubleValue();
    }
    if (right instanceof Float) {
      return number <= right.floatValue();
    }
    if (right instanceof Integer) {
      return number <= right.intValue();
    }
    if (right instanceof Long) {
      return number <= right.longValue();
    }
    if (right instanceof Short) {
      return number <= right.shortValue();
    }
    throw new UnsupportedOperationException();
  }
}
