package brn.swans.route.metric;

import java.util.HashMap;
import java.util.Map;

import jist.runtime.JistAPI;
import jist.swans.mac.MacAddress;
import jist.swans.net.NetAddress;

import org.apache.log4j.Logger;

public class ArpTable implements ArpTableInterface {

  private static Logger log = Logger.getLogger(ArpTable.class.getName());


  // ////////////////////////////////////////////////
  // locals
  //

  /**
   * The IP address of this node.
   */
  private NetAddress localAddr;

  /**
   * Maps neighbors net addresses to mac addresses
   */
  private Map /*NetAddress -> MacAddress*/ arpTable;
  private Map /*MacAddress -> NetAddress*/ rarpTable;


  // ////////////////////////////////////////////////
  // initialization
  //

  /**
   * Constructs a etx route metric object.
   * @param localMacAddr
   */
  public ArpTable(NetAddress localAddr, MacAddress localMacAddr) {
    this.localAddr = localAddr;

    this.arpTable = new HashMap();
    this.rarpTable = new HashMap();

    addArpEntry(localAddr, localMacAddr);
    addArpEntry(NetAddress.LOCAL, MacAddress.LOOP);
    addArpEntry(NetAddress.ANY, MacAddress.ANY);
    addArpEntry(NetAddress.NULL, MacAddress.NULL);
  }


  // ////////////////////////////////////////////////
  // implementation
  //

  /*
   * (non-Javadoc)
   * @see brn.swans.route.metric.ArpTableInterface#addArpEntry(jist.swans.net.NetAddress, jist.swans.mac.MacAddress)
   */
  public void addArpEntry(NetAddress net, MacAddress mac) {
    if (log.isDebugEnabled())
      log.debug(this + "(" + JistAPI.getTime() + "): adding net/mac pair " + net
          + "/" + mac);
    arpTable.put(net, mac);
    rarpTable.put(mac, net);
  }

  /*
   * (non-Javadoc)
   * @see brn.swans.route.metric.ArpTableInterface#getArpEntry(jist.swans.net.NetAddress)
   */
  public MacAddress getArpEntry(NetAddress net) {
    MacAddress macAddress = (MacAddress) arpTable.get(net);
    if (null == macAddress && log.isInfoEnabled())
      log.info(localAddr + "(" + JistAPI.getTime() + "): mac adddress for " + net
        + " not found");
    return macAddress;
  }

  /*
   * (non-Javadoc)
   * @see brn.swans.route.metric.ArpTableInterface#getArpEntry(jist.swans.mac.MacAddress)
   */
  public NetAddress getArpEntry(MacAddress lastHop) {
    NetAddress netAddress = (NetAddress) rarpTable.get(lastHop);
    if (null == netAddress && log.isInfoEnabled())
      log.info(localAddr + "(" + JistAPI.getTime() + "): net adddress for " +
          lastHop + " not found");
    return netAddress;
  }

  /*
   * (non-Javadoc)
   * @see brn.swans.route.metric.ArpTableInterface#removeArpEntry(jist.swans.net.NetAddress)
   */
  public void removeArpEntry(NetAddress net) {
    MacAddress mac = getArpEntry(net);
    arpTable.remove(net);
    if (mac != null)
      rarpTable.remove(mac);
  }

  /*
   * (non-Javadoc)
   * @see brn.swans.route.metric.ArpTableInterface#getArpTable()
   */
  public Map getArpTable() {
    return arpTable;
  }

}
