// ============================================================================
// File:               $File$
//
// Project:            
//
// Purpose:            
//
// Author:             Rammi
//
// Copyright Notice:   (c) 2008  Rammi (rammi@caff.de)
//
// Latest change:      $Date$
//
// History:	       $Log$
//=============================================================================
package de.caff.asteroid.rammi;

import de.caff.asteroid.*;

import java.util.HashMap;
import java.util.Map;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.geom.AffineTransform;

/**
 *  Trying to see the future, standard version.
 */
public class StandardFuturologist
        extends AbstractBasicFuturologist
        implements DrawableProvider
{
  /** Color for drawable provider. */
  private static final Color COLOR = Color.yellow;
  /** Font for drawable provider. */
  private static final Font FONT = new Font("SansSerif", Font.BOLD, 24);
  /** Mapping of asteroid IDs to hit frame counters. */
  private Map<Integer, Integer> asteroidHits = new HashMap<Integer, Integer>();

  /**
   * Called each time a frame is received.
   * <p/>
   * <b>ATTENTION:</b> this is called from the communication thread!
   * Implementing classes must be aware of this and take care by synchronization or similar!
   *
   * @param frame the received frame
   */
  public void frameReceived(FrameInfo frame)
  {
    handleFrameInfo(frame);
  }

  /**
   * Get the number of frames until a game object is destroyed if it doesn't alter its movements.
   *
   * @param ident     ident of game object
   * @param frameInfo frame info of game object
   * @return number of frames till destruction or less than zero if frame is unknown
   */
  protected int getFramesTillDestroyed(Integer ident, FrameInfo frameInfo)
  {
    Integer hitFrame = asteroidHits.get(ident);
    if (hitFrame != null) {
      return hitFrame.intValue() - frameInfo.getIndex();
    }
    return HIT_FRAME_UNKNOWN;
  }

  /**
   * Add a known hit for an asteroid.
   *
   * @param astIdent     asteroid ID
   * @param frameCounter frame counter when hit happens
   */
  protected void addHit(Integer astIdent, int frameCounter)
  {
    Integer currentCounter = asteroidHits.get(astIdent);
    if (currentCounter == null  ||  currentCounter > frameCounter) {
      asteroidHits.put(astIdent, frameCounter);
    }
  }

  /**
   * Forget all knowledge about any asteroids.
   */
  protected void forgetEverything()
  {
    asteroidHits.clear();
  }

  /**
   * Draw information of a frame.
   *
   * @param g     graphics context
   * @param frame frame information
   */
  public void draw(Graphics2D g, FrameInfo frame)
  {
    frameReceived(frame);

    g.setFont(FONT);
    g.setColor(COLOR);
    FontMetrics metrics = g.getFontMetrics();
    for (Asteroid ast: frame.getAsteroids()) {
      int ttl = getFramesTillDestroyed(ast, frame);
      if (ttl >= 0) {
        Point pos = ast.getLocation();
        String txt = Integer.toString(ttl);
        Rectangle2D bbox = metrics.getStringBounds(txt, g);
        AffineTransform oldTrafo = g.getTransform();
        g.translate(pos.x,
                    pos.y );
        g.scale(1, -1);
        g.drawString(txt, (float)-bbox.getCenterX(), (float)-bbox.getCenterY());
        g.setTransform(oldTrafo);
      }
    }
  }
}
