// ============================================================================
// File:               $File$
//
// Project:            
//
// Purpose:            
//
// Author:             Rammi
//
// Copyright Notice:   (c) 2008  Rammi (rammi@caff.de)
//                     This code is in the public domain.
//                     Use at own risk.
//                     No guarantees given.
//
// Latest change:      $Date$
//
// History:	       $Log$
//=============================================================================
package de.caff.asteroid.analysis;

import de.caff.asteroid.Buttons;
import de.caff.asteroid.FrameInfo;
import de.caff.asteroid.PingKeyProvider;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

/**
 *  A frame and the keys which were after it was received.
 *
 *  This class is part of a solution for a
 *  <a href="http://www.heise.de/ct/creativ/08/02/details/">competition by the German computer magazine c't</a>.
 */
public class FrameKeyInfo
{
  public static class ButtonInfo
  {
    /** Timestamp of button send. */
    private long timestamp;
    /** The buttons. */
    private Buttons buttons;
    /** The ping id sent with this buttons. */
    private byte    pingID;

    /**
     *  Constructor used for c't dump file.
     *  @param timestamp timestamp
     *  @param keymask button mask
     */
    ButtonInfo(long timestamp, byte keymask)
    {
      this(timestamp, keymask, (byte)0);
    }

    /**
     *  Constructor.
     *  @param timestamp timestamp
     *  @param keymask   button mask
     *  @param ping      ping ID sent with buttons
     */
    ButtonInfo(long timestamp, byte keymask, byte ping)
    {
      this.timestamp = timestamp;
      this.buttons = new Buttons(keymask);
      this.pingID = ping;
    }

    /**
     *  Get the timestamp when the buttons were sent.
     *  @return timestamp
     */
    public long getTimestamp()
    {
      return timestamp;
    }

    /**
     *  Get the buttons.
     *  @return buttons
     */
    public Buttons getButtons()
    {
      return buttons;
    }

    /**
     *  Get the ping ID sent with this buttons.
     *  @return ping ID
     */
    public byte getPingID()
    {
      return pingID;
    }
  }

  /** The frame info. */
  private FrameInfo frameInfo;
  /** Keys send after frame info was received. */
  private List<ButtonInfo> buttons = new LinkedList<ButtonInfo>();

  /**
   *  Constructor for c't file format.
   *  @param index      frame index
   *  @param timestamp  receive timestamp of frame data
   *  @param frameBytes frame data
   *  @throws IOException if frame data is invalid
   */
  public FrameKeyInfo(int index, long timestamp, byte[] frameBytes) throws IOException
  {
    this(index, timestamp, frameBytes, null);
  }

  /**
   *  Constructor.
   *  @param index      frame index
   *  @param timestamp  receive timestamp of frame data
   *  @param frameBytes frame data
   *  @param pinky      ping key provider
   *  @throws IOException if frame data is invalid
   */
  public FrameKeyInfo(int index, long timestamp, byte[] frameBytes, PingKeyProvider pinky)
          throws IOException
  {
    frameInfo = new FrameInfo(index, frameBytes, pinky, timestamp);
  }

  /**
   *  Add a button info.
   *  @param timestamp send timestamp of button packet
   *  @param keys      buttons sent
   *  @param ping      associated ping
   */
  public void addButtons(long timestamp, byte keys, byte ping)
  {
    buttons.add(new ButtonInfo(timestamp, keys, ping));
  }

  /**
   *  Add a button info.
   *  Used for c't format w/o timestamps and pings.
   *  @param keys buttons sent
   */
  public void addButtons(byte keys)
  {
    buttons.add(new ButtonInfo(frameInfo.getReceiveTime(), keys));
  }

  /**
   *  Get the frame info.
   *  @return frame info
   */
  public FrameInfo getFrameInfo()
  {
    return frameInfo;
  }

  /**
   *  Get the buttons sent after the frame, before next frame was received.
   *  @return buttons
   */
  public List<ButtonInfo> getButtons()
  {
    return buttons;
  }
}
