import Applet2;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Event;

/** アニメーションしながら音を演奏する HandBell クラス */

public class HandBell extends Applet2 implements Runnable {

    /** イメージの数の上限 */

       public static final int limitNumber=32;

    /** アニメーションを操作するのスレッド */

       public Thread animater=null;

    /** アニメーションのイメージ */

       public Image images[];

    /** イメージの読み込み状態 */

       public int imageStates[];

    /** イメージの読み込みをしているか */

       public boolean waitFlag=true;

    /** イメージの数とサイズの最大値 */

       public int maxNumber=0, maxWidth=0, maxHeight=0;

    /** 表示すべきイメージの番号 */

       protected int counter=0;

    /** コマ送りのインターバル（ミリ秒単位） */

       protected int intervalTime=80;

    /** アプレット内のイメージの位置 */

       protected int x, y;

    /** 音のデータ名とディレクトリ名 */

       public String pitch, sound;

    /** 初期設定のメソッド */

       public void init() {

         // パラメータの読み込み

             String anime = getParameter("anime");
             if ( anime == null ) anime = "anime";
             String file = getParameter("file");
             if ( file == null ) file = "handbell";
             sound = getParameter("sound");
             if ( sound == null ) sound = "sound";
             pitch = getParameter("pitch");
             if ( pitch == null ) pitch = "C";
             intervalTime = getIntParameter("interval");
             if( intervalTime > 3000 )  intervalTime=3000;
             if( intervalTime < 50   )  intervalTime=80;

        // イメージの読み込みを開始

             images = new Image[limitNumber];
             imageStates = new int[limitNumber];

             for( int i=0; i<limitNumber; i++ ) {
                  images[i] = getImage( getDocumentBase(),
                                  anime + "/" + file + (i+1) + ".gif" );
             }

             x = 0;  y = 0;
       }

    /** 画面表示（初期）のメソッド */

       public void paint( Graphics g ) {

            if( waitFlag ) {       //まだイメージを読み込み中

                g.drawString( "Please", 4, 20 );
                g.drawString( "Wait..", 4, 40 );

             // イメージを生成するために描画命令が必要（省略不可）

                for( int i=0; i<limitNumber; i++ ) {
                     g.drawImage( images[i],
                                  size().width, size().height, this );
                }
            }
            else {
                if( maxNumber != 0 )
                     g.drawImage( images[0], 0, 0, this );
            }
       }

    /** 画面表示のメソッド */

       public void update( Graphics g ) {

             if( waitFlag ) return;  //まだイメージを読み込み中

             if( 0 <= counter && counter < maxNumber ) {
                  g.clearRect( x, y, maxWidth, maxHeight );
                  g.drawImage( images[counter], x, y , this );
             }
       }

    /** 画面から消えた時に呼ばれる */

       public void start() {
             if( animater == null ) {
                   animater = new Thread(this);
                   animater.start();
             }
       }

    /** 画面から消えた時に呼ばれる */

       public void stop() {
             if( animater != null ) {
                   animater.stop();
                   animater = null;
             }
       }

    /** スレッドの処理の内容 */

       public void run() {

             if( waitFlag ) {
                 while( animater.isAlive() ) {

                  // イメージの読み込みを監視
                      checkStates();
                      try { Thread.sleep( 1000 ); }
                      catch (InterruptedException e){}
                  }
             }

              // アニメーションを開始
            else {
                  if( animater.isAlive() ) {
                      for( counter=0; counter<maxNumber; counter++ ) {
                          repaint();
                          try { Thread.sleep( intervalTime ); }
                          catch (InterruptedException e){}
                      }
                      for( counter=0; counter<maxNumber; counter++ ) {
                          repaint();
                          try { Thread.sleep( intervalTime ); }
                          catch (InterruptedException e){}
                      }
                      counter = 0;
                      repaint();
                  }
             }
       }


    /** イメージの状態を調べる */

       protected void checkStates() {

        // ALLBITS--読み込みが完了  ERROR--読み込めない

            boolean flag = false;
            for( int i=0; i<limitNumber ; i++ ) {

               imageStates[i] = checkImage( images[i], this );
               if( ( imageStates[i] & ALLBITS ) != ALLBITS 
                    && ( imageStates[i] & ERROR ) != ERROR ) {
                  flag = true;  // まだ状態が未確定
                  break;
               }
            }
            waitFlag = flag;

        // すべてのイメージの状態が確定した時に行う処理

            if( !waitFlag ) {

                for( int i=0; i<limitNumber ; i++ ) {
                     if( ( imageStates[i] & ALLBITS ) == ALLBITS ) {
                          maxWidth  = Math.max( maxWidth,
                                          images[i].getWidth(this) );
                          maxHeight = Math.max( maxHeight,
                                          images[i].getHeight(this) );
                          maxNumber = i+1;
                      }
                }
                repaint();  // 最初の絵を表示させる
            }
       }

    /** マウスがクリックされた時の処理 */

       public boolean mouseDown( Event evt, int x, int y ) {

             if( waitFlag ) return true; //まだイメージを読み込み中

             play( getDocumentBase(), sound + "/" + pitch + ".au" );
             animater = null;
             animater = new Thread(this);
             animater.start();

             return true;
       }
}

