/*
 * sceneBuilder.java
 *
 * Created on March 23, 2003, 6:11 PM
 */

/* Massive Includes */
import java.awt.*;
import java.lang.Math;
import java.awt.event.*;
import java.applet.*;
import java.applet.Applet;
import java.io.*;
import java.net.*;
import java.util.*;
import java.beans.*;

/**
 * This class contains all of the information needed to build a scene, which is
 * comprised of a series of radars and targets.
 *
 * @author  Nick Cole
 */
public class sceneBuilder {

    public LatLong ULCorner = new LatLong( 36.0, 125.0 );
    public LatLong LRCorner = new LatLong ( 41.0, 118.0 );
    public double latDiff;
    public double longDiff;
                
    //these store the current number of radars and targets
    public int radarCount = 0;
    public int targetCount = 0;
    
    //stores our radars and targets 
    public Target targetArray[];
    public Radar radarArray[];
    
    //are we in debug mode?
    boolean DEBUG = false;
    
    //a class which can convert latLong coordinates into screenlocs
    public StrikeMap targetMap;
    
    /** Creates a new instance of sceneBuilder */
    public sceneBuilder(StrikeMap newTargetMap) {
        if( newTargetMap == null ){
            System.out.println( "ERROR: NewTarget map was NULL!");
        }   
        targetMap = newTargetMap;
        
        /*get the difference in map coordinates to
        generate the random numbers */
        latDiff = Math.abs( ULCorner.GetLat() - LRCorner.GetLat() );
        longDiff = Math.abs( ULCorner.GetLong() - LRCorner.GetLong() );
    }
    
    /* Adds a new radar to our list of radars
     */
    public void addRadar( Radar newRadar ){
         int i;         //loop
         Radar[] tempRadarArray;

         //create a temp
         tempRadarArray = new Radar[radarCount + 1];
         
         //copy
         for( i = 0; i < radarCount; i++ ){
            tempRadarArray[i] = radarArray[i];
         }
         tempRadarArray[radarCount] = newRadar;
         radarCount++;
         
         //set as master
         radarArray = tempRadarArray;
    }
    
    /* Adds a new target to our list of targets
     */
    public void addTarget( Target newTarget ){
         int i;
         Target[] tempTargetArray;
         tempTargetArray = new Target[targetCount + 1];
         
         for( i = 0; i < targetCount; i++ ){
            tempTargetArray[i] = targetArray[i];
         }
         tempTargetArray[targetCount] = newTarget;
         targetCount++;
         targetArray = tempTargetArray;
    }
    
    public void removeTarget( int index ){
        int i,j;
        Target[] tempTargetArray;
        tempTargetArray = new Target[targetCount-1];
        
        j = 0;
        for( i = 0; i < targetCount; i++ ){
            if( i != index ){
                tempTargetArray[j] = targetArray[i];
                j++;
            }
        }
        targetCount--;
        targetArray = tempTargetArray;
    }
    
    /* Removes a radar from our scene
     * @param index the index of the removed item
     */
    public void removeRadar( int index ){
        int i,j;
        Radar[] tempRadarArray;
        tempRadarArray = new Radar[radarCount-1];
        
        j = 0;
        for( i = 0; i < radarCount; i++ ){
            if( i != index ){
                tempRadarArray[j] = radarArray[i];
                j++;
            }
        }
        radarCount--;
        radarArray = tempRadarArray;
    }
        
    public void generateTargets( int count ){
        int i;                              //loop counter
        targetArray = new Target[count];     //our random targets
        Random rn = new Random();           //random num
        double randLat, randLong;
        Target tempTarget;
        String tempString;                  //used to create a target ID
        LatLong tempLL;
        
        //set our class global to the count
        targetCount = count;
                
        if(DEBUG){
            System.out.println( "latDiff: " + latDiff );
            System.out.println( "longDiff: " + longDiff );
        }

        for( i = 0; i < count; i++ ){
            randLat = Math.abs((rn.nextInt()+rn.nextDouble()) % latDiff) + 
                ULCorner.GetLat();
            randLong = Math.abs((rn.nextInt()+rn.nextDouble()) % longDiff) +
                LRCorner.GetLong();
            
            if(DEBUG){
                System.out.println( "Count: " + i );
                System.out.println( "RandLat: " + randLat );
                System.out.println( "RandLong: " + randLong );
            }
            
            //assign a name to the target
            tempString = "Default";
            switch( (Math.abs(rn.nextInt() % 4)) ){
                case 0:
                    tempString = "Airfield";
                    break;
                case 1:
                    tempString = "Communications Center";
                    break;
                case 2:
                    tempString = "Arms Lab";
                    break;
                case 3:
                    tempString = "Power Plant";
                    break;
            }
            
            tempLL = new LatLong( randLat, randLong );
            
            //create a new target then stick it into the array
            tempTarget = new Target( tempString, tempLL, "0", targetMap, 100.0);
            
            //from the random numbers generated, put the object there
             targetArray[i] = tempTarget;

        }
        
        //output targets ---DEBUG
        if( DEBUG ){
            for( i = 0; i < count; i++ ){
                System.out.println( i + ": " + targetArray[i].toString() );
            }
        }  
    }
    
    //this function creates random radars and positions
    public void generateRadars( int count, double radarRadius, double maxRadius,
        double initStr ){
        int i;                              //loop counter
        radarArray = new Radar[count];      //our random radar
        Random rn = new Random();           //random num
        double randLat, randLong;
        Radar tempRadar;
        LatLong tempLL;
        
        //set our class global to the count
        radarCount = count;
                
        if(DEBUG){
            System.out.println( "In Method: generateRadar()");
            System.out.println( "latDiff: " + latDiff );
            System.out.println( "longDiff: " + longDiff );
        }

        for( i = 0; i < count; i++ ){
            randLat = Math.abs((rn.nextInt()+rn.nextDouble()) % latDiff) +
                ULCorner.GetLat();
            randLong = Math.abs((rn.nextInt()+rn.nextDouble()) % longDiff)
                + LRCorner.GetLong();
            
            if(DEBUG){
                System.out.println( "Count: " + i );
                System.out.println( "randlat: " + randLat );
                System.out.println( "Randlong: " + randLong );
            }
            
            tempLL = new LatLong( randLat, randLong );
                      
            //create a new target then stick it into the array
            tempRadar = new Radar( "Basic Radar", tempLL, "0", targetMap, 100.0,
                radarRadius, maxRadius, initStr);
                       
            //from the random numbers generated, put the object there
             radarArray[i] = tempRadar;
        }
        
        //output targets ---DEBUG
        if( DEBUG ){
            for( i = 0; i < count; i++ ){
                System.out.println(i + ": " + radarArray[i].toString());
            }
        }   
    }
   
    /**
    * Defend Target
    * @param double radarDefendEps - how close to protect targets
    * @author  Nicholas Cole (ncole@cs.unr.edu)
    */
    public void defendTarget(double radarDefendEps){
        int i,j;                                //loop counter
        boolean targetsSafe = false;            //check if targets are safe
        boolean soFarSafe = true;               //checks if targets are safe
        double increaseEps = 10.0;              //how much to increment the radar size
        int maxIterations = 20;                 //how many passes at working it
        int count = 0;                          //assures we don't run too long
        LatLong tempLL;                         //placeholder latlong
        LatLong tempRadLL;
        
        //these variables keep track of the nearest radar
        double closestRadar, tempDist;
        int closestRadarIdx;
        
        //main loop which runs until all targets are protected
        while( !targetsSafe && count < maxIterations ){
            soFarSafe = true;
 
            //walk through each target and check it against
            //each radar to find the closest one
            for(i = 0; i < targetCount; i++ ){
                closestRadar = 10000.0;
                closestRadarIdx = 0;
                for( j = 0; j < radarCount; j++ ){
                   
                   tempLL = targetArray[i].GetLatLong();
                   tempRadLL = radarArray[j].GetLatLong();
                   
                   //this may not be right since it used to be x, y
                   tempDist = distanceTo( tempLL.GetLong(), tempLL.GetLat(),
                        tempRadLL.GetLong(), tempRadLL.GetLat());
                   if( tempDist < closestRadar ){
                    closestRadarIdx = j;
                    closestRadar = tempDist;
                   }
                }
                if( closestRadar < radarArray[closestRadarIdx].GetRadius()/ radarDefendEps ){
                    if( DEBUG ){
                        System.out.println( "Target Inside." );
                    }
                }else{
                    soFarSafe = false;
                    if( (radarArray[closestRadarIdx].ChangeRadius(radarArray[closestRadarIdx].GetRadius()
                     + increaseEps)) ){
                         //nothing
                    }else{
                        //this is where we'd put code to move the radar
                    }                     
                    
                    if( DEBUG ){
                        System.out.println( "Target Outside." );
                    }
                }
            }
            
            //are we safe?  If not, walk this again
            if(soFarSafe == false ){
               // generateRadars( 10, 300.00);
            }else{
                targetsSafe = true;
            }
            count++;
        }     
    }
    
    public void randomRelocateRadar(int index){
       int i;                              //loop counter
       Random rn = new Random();           //random num
       double randLat, randLong;
       LatLong tempLL;
              
       randLat = Math.abs((rn.nextInt()+rn.nextDouble()) % latDiff) + 
            ULCorner.GetLat();
       randLong = Math.abs((rn.nextInt()+rn.nextDouble()) % longDiff) +
            LRCorner.GetLong();

       tempLL = new LatLong( randLat, randLong );
       //set radar's position 
       
       radarArray[index] = new Radar( "Basic Radar", tempLL, "0", targetMap,
        100.0, radarArray[index].GetRadius(), radarArray[index].GetMaxRadius(),
        radarArray[index].GetStr() );
    }
    
    public void randomRelocateTarget(int index){
       int i;                              //loop counter
       Random rn = new Random();           //random num
       double randLat, randLong;
       String tempString;
       LatLong tempLL;
       
       //generate new random location
        randLat = Math.abs((rn.nextInt()+rn.nextDouble()) % latDiff) +
            ULCorner.GetLat();
        randLong = Math.abs((rn.nextInt()+rn.nextDouble()) % longDiff)
            + LRCorner.GetLong();

       //we need to add a function to target which allows us to return
       //all private data members
       tempString = "Ammo Dump";
       
       tempLL = new LatLong( randLat, randLong );
       
        //create a new target then stick it into the array
        targetArray[index] = new Target( tempString, tempLL, "0", targetMap, 100.0);
    }
    
    /* Distance formula 
     */
    
    public double distanceTo( double x1, double y1, double x2, double y2){
        return Math.sqrt(((x2-x1)*(x2-x1)) + ((y2-y1)*(y2-y1)));
    }
    
}
