package com.ibm.wala.analysis.arraybounds.hypergraph.weight;

/**
 * A weight may be not set, a number or unlimited, note that the meaning of unlimited is given by
 * the chosen order (see {@link NormalOrder} and {@link ReverseOrder}).
 *
 * @author Stephan Gocht {@code <stephan@gobro.de>}
 */
public class Weight {
  public enum Type {
    NUMBER,
    NOT_SET,
    UNLIMITED
  }

  public static final Weight UNLIMITED = new Weight(Type.UNLIMITED, 0);
  public static final Weight NOT_SET = new Weight(Type.NOT_SET, 0);

  public static final Weight ZERO = new Weight(Type.NUMBER, 0);

  private final Type type;
  private final int number;

  public Weight(int number) {
    this.type = Type.NUMBER;
    this.number = number;
  }

  public Weight(Type type, int number) {
    super();
    this.type = type;
    this.number = number;
  }

  /**
   * Returns this + other. If this is not Number this will be returned, if other is not number other
   * will be returned
   *
   * @return this + other
   */
  public Weight add(Weight other) {
    Weight result = null;
    if (this.getType() == Type.NUMBER) {
      if (other.getType() == Type.NUMBER) {
        result = new Weight(Type.NUMBER, this.getNumber() + other.getNumber());
      } else {
        result = other;
      }
    } else {
      result = this;
    }

    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (obj == null) {
      return false;
    }
    if (this.getClass() != obj.getClass()) {
      return false;
    }
    final Weight other = (Weight) obj;
    if (this.number != other.number) {
      return false;
    }
    if (this.type != other.type) {
      return false;
    }
    return true;
  }

  public int getNumber() {
    return this.number;
  }

  public Type getType() {
    return this.type;
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + this.number;
    result = prime * result + ((this.type == null) ? 0 : this.type.hashCode());
    return result;
  }

  @Override
  public String toString() {
    if (this.type == Type.NUMBER) {
      return Integer.toString(this.number);
    } else {
      if (this.type == Type.NOT_SET) {
        return "NOT_SET";
      } else if (this.type == Type.UNLIMITED) {
        return "UNLIMITED";
      } else {
        return "Type: " + this.type;
      }
    }
  }
}
