package jist.swans;

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

import jist.swans.app.AbstractApplication;
import jist.swans.field.AbstractField;
import jist.swans.field.Field;
import jist.swans.mac.AbstractMac;
import jist.swans.misc.Location;
import jist.swans.net.AbstractNet;
import jist.swans.radio.AbstractRadio;
import jist.swans.radio.RadioNoise;
import jist.swans.route.AbstractRoute;
import jist.swans.trans.AbstractTrans;

import org.apache.log4j.Logger;

/**
 * Compound holding all entities making up a (wireless) node.
 *
 * @author kurth
 */
public class Node {

  /**
   * IP logger.
   */
  public static final Logger log = Logger.getLogger(Node.class.getName());

  // ////////////////////////////////////////////////
  // constants
  //

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

  protected List fields;

  protected List radios;

  protected List macs;

  protected AbstractNet net;

  protected AbstractRoute route;

  protected List transports;

  protected List applications;

  private int nodeId;

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

  public Node(int nodeId) {
    this.fields = new ArrayList();
    this.radios = new ArrayList();
    this.macs = new ArrayList();
    this.transports = new ArrayList();
    this.applications = new ArrayList();
    this.nodeId = nodeId;
  }


  // ////////////////////////////////////////////////
  // accessors
  //

  public int getNodeId() {
    return nodeId;
  }

  public AbstractNet getNet() {
    return net;
  }

  public AbstractRoute getRoute() {
    return route;
  }

  protected List getApplications() {
    return applications;
  }

  protected List getFields() {
    return fields;
  }

  public List getMacs() {
    return macs;
  }

  public List getRadios() {
    return radios;
  }

  public List getTransports() {
    return transports;
  }

  protected void setFields(List fields) {
    this.fields = fields;
  }

  protected void setMacs(List macs) {
    this.macs = macs;
  }

  protected void setRadios(List radios) {
    this.radios = radios;
  }

  protected void setTransports(List transports) {
    this.transports = transports;
  }

  protected void setApplications(List applications) {
    this.applications = applications;
  }

  public void setNet(AbstractNet net) {
    this.net = net;
    net.setNode(this);
  }

  public void setRoute(AbstractRoute route) {
    this.route = route;
    if (null != route)
      route.setNode(this);
  }

  // ////////////////////////////////////////////////
  // overwrites
  //

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

  public AbstractApplication getApplication(int i) {
    return (AbstractApplication)applications.get(i);
  }

  public AbstractMac getMac(int i) {
    return (AbstractMac)macs.get(i);
  }

  public AbstractRadio getRadio(int i) {
    return (AbstractRadio)radios.get(i);
  }

  public Field getField(int i) {
    return (Field)fields.get(i);
  }

  public AbstractTrans getTransport(int i) {
    return (AbstractTrans)transports.get(i);
  }


  public void addApplication(AbstractApplication app) {
    applications.add(app);
  }

  public void addMac(AbstractMac mac) {
    macs.add(mac);
    mac.setNode(this);
  }

  public void addRadio(AbstractRadio radio) {
    radios.add(radio);
    radio.setNode(this);
  }

  public void addField(AbstractField field) {
    fields.add(field);
    field.addNode(this);
  }

  public void addTransport(AbstractTrans  trans) {
    transports.add(trans);
    trans.setNode(this);
  }


  /**
   * @return the location of the node
   */
  public Location getNodeLocation() {
    Integer id = ((RadioNoise)getRadio(0)).getRadioInfo().getIdInteger();
    return getField(0).getRadioData(id).getLoc();
  }


  public int hashCode() {
    final int PRIME = 31;
    int result = 1;
    result = PRIME * result + nodeId;
    return result;
  }


  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    final Node other = (Node) obj;
    if (nodeId != other.nodeId)
      return false;
    return true;
  }


  public String toString() {
    return "Node " + nodeId;
  }

}
