// ============================================================================
// 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;

/**
 *  Helper class used for sychronized access to buttons.
 *
 *  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 Buttons
        implements GameData
{
  /** The key mask. */
  private byte keys;

  /**
   *  Default constructor.
   *  Intializes buttons with {@link #NO_BUTTON}.
   */
  public Buttons()
  {
    this(NO_BUTTON);
  }

  /**
   *  Constructor.
   *  @param keyMask initial button mask
   */
  public Buttons(int keyMask)
  {
    keys = (byte)keyMask;
  }

  /**
   *  Set a key bit to on or off.
   *  @param key key bit
   *  @param on  <code>true</code> for on, <code>false</code> for off
   */
  public synchronized void setKey(int key, boolean on)
  {
    if (on) {
      keys |= key;
    }
    else {
      keys &= ~key;
    }
  }

  /**
   *  Set the key mask.
   *  @param keys key mask
   */
  public synchronized void setKeys(int keys)
  {
    this.keys = (byte)keys; 
  }

  /**
   *  Clear all keys.
   */
  public synchronized void clearKeys()
  {
    keys = NO_BUTTON;
  }

  /**
   *  Get the key mask and clear it.
   *  @return current key mask before clearing
   */
  public synchronized byte extractKeys()
  {
    byte ret = keys;
    keys = NO_BUTTON;
    return ret;
  }

  /**
   *  Get the key mask.
   *  @return key mask
   */
  public synchronized byte getKeys()
  {
    return keys;
  }

  /**
   *  Is one of the buttons defined by the key mask pressed?
   *  @param keyMask key mask
   *  @return the answer
   */
  public synchronized boolean isAnyPressed(int keyMask)
  {
    return (keys & keyMask) != 0;
  }

  /**
   *  Is exactly the given key mask pressed?
   *  @param keyMask key mask
   *  @return the answer
   */
  public synchronized boolean isPressed(int keyMask)
  {
    int combined = keys & keyMask;
    return combined == keys  &&  combined == keyMask;
  }

  /**
   *  Is the FIRE button pressed?
   *  @return the answer
   */
  public synchronized boolean isFirePressed()
  {
    return isAnyPressed(BUTTON_FIRE);
  }

  /**
   *  Is the HYPERSPACE button pressed?
   *  @return the answer
   */
  public synchronized boolean isHyperspacePressed()
  {
    return isAnyPressed(BUTTON_HYPERSPACE);
  }

  /**
   *  Is the THRUST button pressed?
   *  @return the answer
   */
  public synchronized boolean isThrustPressed()
  {
    return isAnyPressed(BUTTON_THRUST);
  }

  /**
   *  Is the LEFT button pressed?
   *  @return the answer
   */
  public synchronized boolean isLeftPressed()
  {
    return isAnyPressed(BUTTON_LEFT);
  }

  /**
   *  Is the RIGHT button pressed?
   *  @return the answer
   */
  public synchronized boolean isRightPressed()
  {
    return isAnyPressed(BUTTON_RIGHT);
  }

  /**
   *  Is the START button pressed?
   *  @return the answer
   */
  public synchronized boolean isStartPressed()
  {
    return isAnyPressed(BUTTON_START);
  }

  /**
   * Returns a string representation of the object (not synchronized).
   * @return a string representation of the object.
   */
  @Override
  public String toString()
  {
    if (keys == NO_BUTTON) {
      return "<>";
    }
    else {
      StringBuilder builder = new StringBuilder();
      if ((keys & BUTTON_FIRE) != 0) {
        builder.append("<FIRE>");
      }
      if ((keys & BUTTON_HYPERSPACE) != 0) {
        builder.append("<HYPER>");
      }
      if ((keys & BUTTON_LEFT) != 0) {
        builder.append("<LEFT>");
      }
      if ((keys & BUTTON_RIGHT) != 0) {
        builder.append("<RIGHT>");
      }
      if ((keys & BUTTON_THRUST) != 0) {
        builder.append("<THRUST>");
      }
      if ((keys & BUTTON_START) != 0) {
        builder.append("<START>");
      }
      return builder.toString();
    }
  }
}
