/*
 * the model, for spacewars
 * Burton Rosenberg
 * May 2004
 */
 
import java.awt.Dimension ;
 
class TheModel 
implements Runnable {
        
        private static final double THRUST_INCR = 0.1 ;
        private static final double TIME_INCR = 0.5 ;
        private static final int THREAD_SLEEP = 50 ; // in milliseconds
        
        TheView tv ;
        TheController tc ;
        Thread th ;
        StarModule sm ;
        boolean enableStars = false ; // do not set true until TheView
                                      // has dimensions
        
        double x_location = 0.0 ;
        double y_location = 0.0 ;
        double theta = 0.0 ;
        boolean thrustOn = false ;
        boolean needsRotateUpdate = true ;
        
        double vx = 0.0 ;
        double vy = 0.0 ;
     
        void setTheView(TheView tv) { this.tv = tv ; }
        
        TheModel() {
              sm = new StarModule() ;
              th = new Thread(this) ;  
              th.start() ; // must be after all variables are initialized
        }
        
        void setTheController(TheController tc) { this.tc = tc ; }
        
        double getXlocation() { return x_location ; }
        
        double getYlocation() { return y_location ; }
        
        double getTheta() { return theta ; }
        
        int [] getStarX () { 
            if ( !enableStars ) return null ;
            return sm.projectedX ;
        }

        int [] getStarY () { 
            if ( !enableStars ) return null ;
            return sm.projectedY ;
        }

        boolean isThrustOn() { return thrustOn ; }
        
        boolean isNeededRotateUpdate() { 
                boolean b = needsRotateUpdate ;
                needsRotateUpdate = false ;
                return b ;
        }
        
        void setEnableStars(boolean state) { enableStars = state ; }

        void setTheta(double theta) {
            this.theta = theta ;
            // ASSERT: write theta then set needsUpdate true,
            // set needsUpdate false then read theta, else
            // a critical race
            needsRotateUpdate = true ;
            tv.repaint() ;
        }
        
        void setThrust(boolean isOn) {
             thrustOn = isOn ;
             //tv.repaint() ;
        }
        
        public void run() {

           // update x_offset and y_offset based on rocket's velocity
           try { while( true ) {

                   th.sleep ( THREAD_SLEEP ) ;
                   if (tv==null) continue ; // wait until tv initalized ;

                   // update thrust
                   if ( thrustOn ) {
                     double dvy = - Math.cos(theta) * THRUST_INCR ;
                     double dvx = - Math.sin(theta) * THRUST_INCR ;
                     vy += dvy ;
                     vx += dvx ;
                   }

                   // update location
                   x_location += vx * TIME_INCR ;
                   y_location += vy * TIME_INCR ;

                   // wrap around
                   Dimension d = tv.getSize() ;
                   int x_wrap = d.width/2 ;
                   int y_wrap = d.height/2 ;
                   
                   if ( y_location < -y_wrap ) y_location = y_wrap ;
                   else if ( y_location > y_wrap ) y_location = -y_wrap ;
                   if ( x_location < -x_wrap ) x_location = x_wrap ;
                   else if ( x_location > x_wrap ) x_location = -x_wrap ;
          
                   if ( enableStars ) sm.moveStars(d) ;
                   tv.repaint() ;
                   
 //System.out.println("(vx,vy)"+vx+", "+vy) ;
           } } // close try and while(true) 
           catch( InterruptedException ie ) {  
           }
           
        }
}
