/*
 * $Id: BulletML2SWF.java,v 1.4 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 org.xml.sax.ErrorHandler;
import org.xml.sax.SAXParseException;
import org.w3c.dom.Document;
import java.util.*;
import java.io.*;

/**
 * BulletML to SWF bootstrap.
 *
 * @version $Revision: 1.4 $
 */
public class BulletML2SWF {

  private int tx, ty, td;
  private float rank;
  private String dtdUrl;

  private GameManager gameManager;

  private void checkVerticalHorizontal(String document) {
    try {
      Document doc = UJAXP.getValidDocument(new StringReader(document));
      Bulletml bulletML = new Bulletml(doc);
      String type = bulletML.getType();
      if ( type != null && type.equals("horizontal") ) {
        if ( gameManager.screenWidth <= 0 ) {
          gameManager.screenWidth = 320<<8;
          gameManager.screenHeight = 240<<8;
        }
        tx = (gameManager.screenWidth>>2)*3;
        ty =  gameManager.screenHeight>>1;
        td = 270;
        gameManager.setShipPos((gameManager.screenWidth>>2), (ty>>3)*7);
      } else {
        if ( gameManager.screenWidth <= 0 ) {
          gameManager.screenWidth = 240<<8;
          gameManager.screenHeight = 320<<8;
        }
        tx = gameManager.screenWidth>>1;
        ty = gameManager.screenHeight>>2;
        td = 0;
        gameManager.setShipPos((tx>>3)*7, ty*3);
      }
    } catch ( Exception e ) {
      return;
    }
  }

  private IActionElmChoice[] loadBulletML(String document) {
    try {
      ErrorHandler errorHandler = new ErrorHandler() {
        public void error(SAXParseException e) {
          e.printStackTrace();
        }
        public void fatalError(SAXParseException e) {
          e.printStackTrace();
        }
        public void warning(SAXParseException e) {
          e.printStackTrace();
        }
      };
      Document doc = UJAXP.getValidDocument(
       new StringReader(document), errorHandler);
      Bulletml bulletML = new Bulletml(doc);
      IBulletmlChoice[] bmc = bulletML.getContent();
      Vector aecVct = new Vector();
      BulletmlUtil.clear();
      for ( int i=0 ; i<bmc.length ; i++ ) {
        IBulletmlChoice be = bmc[i];
        if ( be instanceof Action ) {
          Action act = (Action)be;
          if ( act.getLabel().startsWith("top") ) {
            aecVct.addElement(act);
          }
          BulletmlUtil.addAction(act);
        } else if ( be instanceof Bullet ) {
          BulletmlUtil.addBullet((Bullet)be);
        } else if ( be instanceof Fire ) {
          BulletmlUtil.addFire((Fire)be);
        }
      }
      IActionElmChoice[] topAction = new IActionElmChoice[aecVct.size()];
      aecVct.copyInto(topAction);
      return topAction;
    } catch ( Exception e ) {
      e.printStackTrace();
      return null;
    }
  }

  private void usage() {
    System.err.println(
     "Usage: bulletml2swf [-rank n] [-width n] [-height n] [-interval n] [-dtdurl URL] [-o name] file [file2 ...]");
  }

  private int FILE_MAX = 64;
  private String[] fileName = new String[FILE_MAX];
  private int flIdx;

  private int interval = 120;

  private String outputFileName = null;

  private void parseArgs(String[] args) throws IOException {
    flIdx = 0;
    for ( int i=0 ; i<args.length ; i++ ) {
      if ( args[i].equals("-rank") ) {
        rank = (float)Double.parseDouble(args[i+1]); i++;
      } else if ( args[i].equals("-width") ) {
        gameManager.screenWidth = Integer.parseInt(args[i+1])<<8; i++;
      } else if ( args[i].equals("-height") ) {
        gameManager.screenHeight = Integer.parseInt(args[i+1])<<8; i++;
      } else if ( args[i].equals("-interval") ) {
        interval = Integer.parseInt(args[i+1]); i++;
      } else if ( args[i].equals("-dtdurl") ) {
        dtdUrl = args[i+1]; i++;
      } else if ( args[i].equals("-o") ) {
        outputFileName = args[i+1]; i++;
      } else if ( args[i].startsWith("-") )  {
        throw new IOException("Invalid args.");
      } else {
        fileName[flIdx] = args[i];
        flIdx++;
        if ( flIdx >= FILE_MAX ) {
          throw new IOException("Too many files.");
        }
      }
    }
  }

  private String getDTDReplacedStr(String fn)
   throws FileNotFoundException, IOException {
    // Replace DTD URL.
    StringBuffer buf = new StringBuffer();
    File file = new File(fn);
    BufferedReader reader = new BufferedReader(new FileReader(file));
    for ( ; ; ) {
      String ln = reader.readLine();
      if ( ln == null ) break;
      buf.append(ln);
    }
    String doc = buf.toString();
    if ( dtdUrl != null ) {
      int dtSt = doc.indexOf("<!DOCTYPE");
      int dtEd = doc.indexOf(">", dtSt+1) + 1;
      doc = doc.substring(0, dtSt) +
       "<!DOCTYPE bulletml SYSTEM \"" + dtdUrl + "\">" +
       doc.substring(dtEd);
    }
    return doc;
  }

  public BulletML2SWF(String[] args) throws IOException {
    dtdUrl = null;
    rank = 0.5f;
    gameManager = new GameManager();
    gameManager.screenWidth = 0;

    try {
      parseArgs(args);
    } catch ( Exception e ) {
      usage();
      return;
    }
    if ( flIdx <= 0 ) {
      usage();
      return;
    }

    if ( outputFileName == null ) {
      int sfIdx = fileName[0].lastIndexOf(".");
      outputFileName = fileName[0].substring(0, sfIdx) + ".swf";
    }

    checkVerticalHorizontal(getDTDReplacedStr(fileName[0]));
    gameManager.init();

    for ( int i=0 ; i<flIdx ; i++ ) {
      IActionElmChoice[] actions;
      actions = loadBulletML(getDTDReplacedStr(fileName[i]));
      if ( actions == null ) return;

      gameManager.addTopBullet(actions, tx, ty, td, rank);
      int wc;
      if ( i == flIdx-1 ) wc = -1;
      else wc = interval;
      gameManager.loop(wc);
    }

    gameManager.putMovie(outputFileName);
  }

  public static void main(String[] args) {
    try {
      new BulletML2SWF(args);
    } catch ( IOException e ) {
      e.printStackTrace();
    }
  }
}
