// ============================================================================
// 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.Communication;
import de.caff.asteroid.FrameInfo;
import de.caff.asteroid.FrameListener;

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

/**
 */
public class MultiGamesPlayer
        implements FrameListener
{
  private static final int GAMES_TO_PLAY = 10;
  static final int FRAMES_COUNT = 3 * 60 * 60;
  /** The communication used. */
  private Communication com;
  /** The current asteroid player. */
  private AsteroidPlayer asteroidPlayer;
  /** The suicide player to end the game. */
  private SuicidePlayer suicidePlayer;
  /** The start frame. */
  private int startFrame;
  private Writer writer;
  private int gamesToPlay = -1;
  private int score = 0;
  private PlayerPreparer preparer;
  private String note;
  private int maxScore = 0;
  private String maxNote;

  public MultiGamesPlayer(Communication com, PlayerPreparer preparer)
  {
    try {
      writer = new FileWriter("multi.out");
    } catch (IOException e) {
      e.printStackTrace();
    }
    this.com = com;
    suicidePlayer = new SuicidePlayer(com);
    com.addFrameListener(suicidePlayer);
    this.preparer = preparer;
    MemoryHog.oinkOink();
  }

  private void storeResults()
  {
    storeLine("---------------------------------------------------");
    storeLine("Average: "+(score/(double)GAMES_TO_PLAY));
    storeLine("===================================================");
    if (score > maxScore) {
      maxScore = score;
      maxNote = note;
    }
  }

  private void storeLine(String line)
  {
    System.out.println(line);
    try {
      writer.append(line);
      writer.append("\n");
      writer.flush();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  private AsteroidPlayer getNextPlayer()
  {
    if (gamesToPlay-- > 0) {
      AsteroidPlayer player = new AsteroidPlayer(com);
      preparer.prepare(player);
      return player;
    }
    if (gamesToPlay == -1) {
      storeResults();
    }
    note = preparer.advance();
    if (note == null) {
      // ready
      storeLine("Best setting: "+maxNote);
      try {
        writer.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
      System.exit(0);
      return null;
    }
    gamesToPlay = GAMES_TO_PLAY;
    score = 0;
    storeLine("===================================================");
    storeLine("Starting: "+note);
    storeLine("---------------------------------------------------");
    return getNextPlayer();    
  }

  private void storeScore(int gameScore)
  {
    storeLine("Score: "+gameScore);
    score += gameScore;
  }

  /**
   * 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)
  {
    if (frame.isGameEndDisplayed()) {
      if (asteroidPlayer != null) {
        // premature end
        com.removeFrameListener(asteroidPlayer);
        asteroidPlayer.destroy();
        asteroidPlayer = null;
        storeScore(frame.getScore());
      }
      else if (suicidePlayer != null) {
        com.removeFrameListener(suicidePlayer);
        suicidePlayer = null;
      }
    }
    else if (frame.isGameRunning()) {
      if (asteroidPlayer != null  &&  frame.getIndex() - startFrame >= FRAMES_COUNT) {
        com.removeFrameListener(asteroidPlayer);
        asteroidPlayer.destroy();
        asteroidPlayer = null;
        suicidePlayer = new SuicidePlayer(com);
        storeScore(frame.getScore());
        com.addFrameListener(suicidePlayer);
      }
    }
    else {  // Game start displayed
      startFrame = frame.getIndex();
      if (asteroidPlayer == null  &&  suicidePlayer == null) {
        asteroidPlayer = getNextPlayer();
        com.addFrameListener(asteroidPlayer);
      }
    }
  }
}