package brn.swans.route.metric;

import jist.swans.net.NetAddress;
import org.apache.log4j.Logger;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

/**
 * Tracks bit-rate capabilities of other stations.
 * <p/>
 * Java Click-Port.
 *
 * @author zubow
 */
public class AvailableRates {

  /**
   * logger.
   */
  private static Logger log = Logger.getLogger(AvailableRates.class.getName());

  protected static class DstInfo {
    protected NetAddress ip;

    protected List /* int */rates;

    public DstInfo() {
    }

    public DstInfo(NetAddress ip) {
      this.ip = ip;
    }

    public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;

      final DstInfo dstInfo = (DstInfo) o;

      if (ip != null ? !ip.equals(dstInfo.ip) : dstInfo.ip != null) return false;
      if (rates != null ? !rates.equals(dstInfo.rates) : dstInfo.rates != null) return false;

      return true;
    }

    public int hashCode() {
      int result;
      result = (ip != null ? ip.hashCode() : 0);
      result = 29 * result + (rates != null ? rates.hashCode() : 0);
      return result;
    }
  }

  public final static int PROBE_AVAILABLE_RATES = (1 << 0);

  /* NetAddress -> DstInfo */
  protected Hashtable rtable;

  private List /* int */defaultRates;

  /* constructor with default rates */
  public AvailableRates(List rates) {
    defaultRates = new ArrayList();
    defaultRates.addAll(rates);
    rtable = new Hashtable();
  }

  /* constructor for rates for a given NetAddress. */
  public AvailableRates(NetAddress netIp, List rates) {
    DstInfo d = new DstInfo(netIp);
    d.rates = rates;
    d.ip = netIp;

    rtable = new Hashtable();
    rtable.put(netIp, d);
  }

  // ------------------------------------------------------------------------
  // methods
  // ------------------------------------------------------------------------

  /**
   * Returns the a List of rates for a given NetAddress.
   */
  public List /* int */lookup(NetAddress ip) {

    if (ip == null) {
      if (log.isDebugEnabled())
        log.debug("lookup called with NULL ip!");
      return new ArrayList();
    }

    DstInfo dst = (DstInfo) rtable.get(ip);
    if (dst != null) {
      return dst.rates;
    }

    if ((defaultRates != null) && (defaultRates.size() > 0)) {
      return defaultRates;
    }

    return new ArrayList();
  }

  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    final AvailableRates that = (AvailableRates) o;

    if (defaultRates != null ? !defaultRates.equals(that.defaultRates) : that.defaultRates != null) return false;
    if (rtable != null ? !rtable.equals(that.rtable) : that.rtable != null) return false;

    return true;
  }

  public int hashCode() {
    int result;
    result = (rtable != null ? rtable.hashCode() : 0);
    result = 29 * result + (defaultRates != null ? defaultRates.hashCode() : 0);
    return result;
  }
}
