/*
 * $Id: GameManager.java,v 1.3 2002/06/15 14:50:21 kenta Exp $
 *
 * Copyright 2002 Kenta Cho. All rights reserved.
 */
package jp.gr.java_conf.abagames.bulletml2swf;

import jp.gr.java_conf.abagames.bulletml.*;
import jp.gr.java_conf.abagames.util.*;
import java.io.*;
import java.util.Vector;
import java.util.Random;
import java.awt.TextArea;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXParseException;
import org.w3c.dom.Document;
import com.anotherbigidea.flash.interfaces.*;
import com.anotherbigidea.flash.writers.*;
import com.anotherbigidea.flash.structs.*;
import com.anotherbigidea.flash.movie.*;

/**
 * Handle game status.
 *
 * @version $Revision: 1.3 $
 */
public class GameManager {
  private final int BULLET_MAX = 256;
  private BulletImpl[] bullet = new BulletImpl[BULLET_MAX];
  private int bltIdx = 0;

  private final int ACTION_MAX = 1024;
  private ActionImpl[] action = new ActionImpl[ACTION_MAX];
  private int actIdx = 0;

  public int screenWidth, screenHeight;
  public int shipx, shipy;

  private Movie movie;
  private Frame frame;

  public void init() {
    for ( int i=0 ; i<bullet.length ; i++ ) {
      bullet[i] = new BulletImpl(this);
    }
    for ( int i=0 ; i<action.length ; i++ ) {
      action[i] = new ActionImpl(this);
    }
    initShapes();

    movie = new Movie();
    movie.setFrameRate(60);
    movie.setWidth(screenWidth>>8);
    movie.setHeight(screenHeight>>8);
    frame = movie.appendFrame();
  }

  public void setShipPos(int x, int y) {
    shipx = x; shipy = y;
  }

  public BulletImpl getBulletImplInstance(int clr) {
    for ( int i=BULLET_MAX-1 ; i>=0 ; i-- ) {
      bltIdx++; bltIdx &= (BULLET_MAX-1);
      if ( bullet[bltIdx].x == BulletImpl.NOT_EXIST ) {
        bullet[bltIdx].inst =
         frame.placeSymbol(bulletShape[clr%COLOR_NUM], -9999, -9999);
        return bullet[bltIdx];
      }
    }
    return null;
  }

  public void removeBullet(Instance inst) {
    frame.remove(inst);
  }

  public ActionImpl getActionImplInstance() {
    for ( int i=ACTION_MAX-1 ; i>=0 ; i-- ) {
      actIdx++; actIdx &= (ACTION_MAX-1);
      if ( action[actIdx].pc == ActionImpl.NOT_EXIST ) {
        return action[actIdx];
      }
    }
    return null;
  }

  private int bulletNum;

  private void moveBullets() {
    bulletNum = 0;
    for ( int i=BULLET_MAX-1 ; i>=0 ; i-- ) {
      if ( bullet[i].x != BulletImpl.NOT_EXIST ) {
        bullet[i].move();
        bulletNum++;
      }
    }
  }

  private void drawBullets() {
    for ( int i=BULLET_MAX-1 ; i>=0 ; i-- ) {
      if ( bullet[i].x != BulletImpl.NOT_EXIST ) {
        bullet[i].draw();
      }
    }
  }

  private void gameMove() {
    moveBullets();
  }

  private void gameDraw() {
    drawBullets();
  }

  BulletImpl topBullet = null;

  public void addTopBullet(IActionElmChoice[] actions,
   int x, int y, int d, float rank) {
    if ( topBullet != null ) {
      topBullet.vanish();
    }
    topBullet = getBulletImplInstance(0);
    topBullet.set(actions, x, y, d, 0, rank);
  }

  public void drawBullet(double x, double y, int d, int cl, Instance inst) {
    double radians = d * Math.PI / 128.0;

    Transform trs = new Transform(radians, x, y);
    frame.alter(inst, trs, null);
  }

  private Shape[] bulletShape;
  private final int BS_WIDTH = 4, BS_HEIGHT = 8;
  private final int COLOR_NUM = 3;

  private void initShapes() {
    Color[] clrs = {
      new Color(255, 0, 0),
      new Color(0, 255, 0),
      new Color(0, 0, 255),
    };
    bulletShape = new Shape[COLOR_NUM];
    for ( int i=0 ; i<COLOR_NUM ; i++ ) {
      bulletShape[i] = new Shape();
      bulletShape[i].defineFillStyle(clrs[i]);
      bulletShape[i].defineLineStyle(2.0, new Color(0,0,0));
      bulletShape[i].setRightFillStyle(1);
      bulletShape[i].setLineStyle(1);
      bulletShape[i].move(-BS_WIDTH, -BS_HEIGHT);
      bulletShape[i].line( BS_WIDTH, -BS_HEIGHT);
      bulletShape[i].line( BS_WIDTH,  BS_HEIGHT);
      bulletShape[i].line(-BS_WIDTH,  BS_HEIGHT);
      bulletShape[i].line(-BS_WIDTH, -BS_HEIGHT);
    }
  }

  private int cnt, endCnt;
  private final int MAX_FRAME = 60*60;

  public void loop(int waitCnt) throws IOException {
    cnt = endCnt = 0;
    for ( ; ; ) {
      frame = movie.appendFrame();
      gameMove();
      gameDraw();
      cnt++;
      if ( cnt > MAX_FRAME ) break;
      if ( topBullet.isAllActionFinished() ) {
        if ( waitCnt < 0 ) {
          if ( bulletNum <= 1 ) break;
        } else {
          endCnt++;
          if ( endCnt >= waitCnt ) break;
        }
      }
    }
  }

  public void putMovie(String outputFileName) throws IOException {
    movie.write(outputFileName);
  }
}
