package brn.analysis.dump;

import java.io.IOException;
import java.util.Arrays;

import jist.swans.Constants;
import jist.swans.mac.MacAddress;

import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;

import brn.sim.data.dump.WiresharkDump;
import brn.sim.data.dump.WiresharkMessage;

/**
 * Calculate a time series of ack response times, calc mean and variance
 *
 * Calculate number of correct/false - positives/negatives
 *
 * @author kurth
 */
public class AckArrival {

  public static final Logger log = Logger.getLogger(AckArrival.class
      .getName());

  protected static final MacAddress ADDR_DEST = new MacAddress("00:CA:FF:EE:BA:BE");

  private int packets;

  private int fail;

  private void analyzePacket(WiresharkMessage msg, long time) {
    byte[] packet = new byte[msg.getPayload().getSize()];
    msg.getPayload().getBytes(packet, 0);

    byte[] addr1 = IEEE80211Header.getAddr1(packet, AthdescHeader.HEADER_BASE_SIZE);
    byte[] addr2 = IEEE80211Header.getAddr2(packet, AthdescHeader.HEADER_BASE_SIZE);

    // if data frame, collect timing
    if (!AthdescHeader.getTxFeedback(packet, 0)
        ||!Arrays.equals(ADDR_DEST.getAddress(), addr1)
        ||null == addr2)
      return;

    this.packets++;
    if (AthdescHeader.getTxFail(packet, 0))
      this.fail++;

    // TODO look for false positives
  }

  private void analyze(String fileName) throws IOException {
    log.info("Analyzing " + fileName);

    WiresharkDump dump = new WiresharkDump();
    dump.open(fileName);

    // Iterate through the dump
    long start = -1;
    for (WiresharkMessage msg = dump.read(); null != msg; msg = dump.read()) {
      long time = msg.getTv_sec() * Constants.SECOND
        + msg.getTv_usec() * Constants.MICRO_SECOND;
      if (-1 == start)
        start = time;
      time -= start;

      analyzePacket(msg, time);
    }
  }

  private void finished() {
    System.out.println("packets: "+packets+", fail: "+fail);
  }

  protected static void usage() {
    System.out.println("AckTiming txfeedback.pcap");
    System.out.println("  txfeedback.pcap must be with athdesc header");
    // [must be with prism2 header]
  }

  public static void main(String[] args) throws IOException {
    PatternLayout layout = new PatternLayout( "%d{ISO8601} %-5p [%t] %c: %m%n" );
    ConsoleAppender consoleAppender = new ConsoleAppender( layout );
    log.addAppender( consoleAppender );
    log.setLevel(Level.FATAL);

    if (1 != args.length) {
      usage();
      return;
    }

    AckArrival p = new AckArrival();
    for (int i = 0; i < args.length; i++) {
      p.analyze(args[i]);
    }
    p.finished();
  }

}
