/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package gUI;

import coords.CharaPath;
import coords.Coords;
import coords.DCoords;
import java.awt.Image;
import java.util.ArrayList;
import java.util.Observable;
import scenery.Scenery;
import unit.*;

/**
 *
 * @author Alexander The 1st
 */
public class CombatModel extends Observable{
    public Unit currentUseUnit;
    public Unit[] heroes;
    public Enemy[] numbers;
    public Scenery[] barriers;
    
    
    
    //These indicate the far edges of the map
    public int farRight, farDown, level;
    
    public CombatModel(double INIT_X, double INIT_Y, double INIT_Z, int levela){
        super();
        //So when spawning the characters - each  grid icon is lined up for every 40 atm.
        //This means that for now, characters should spawn on 20 area, then 40, 80, etc.
         Coords something = new DCoords(60, 20, 100, 1, new DCoords(INIT_X, INIT_Y, INIT_Z, 1, new Coords(0, 0, 0, 1)));
        //currentUseUnit = new Pirate(new Coords(INIT_X, INIT_Y*4), this);
        currentUseUnit = new Unit(something, "a", "b");
        heroes = new Unit[1];
        heroes[0] = currentUseUnit;
        level = levela;
        this.farRight = 600 * level;
        this.farDown = 600 * level;
        
        numbers = new Enemy[(int) Math.pow(2, level)];
        barriers = new Scenery[(int) Math.pow(2, level)];
        
        for (int a = 0; a < barriers.length; a++) {
            double squareOrEllipse = Math.random();
            double randomX = (Math.round((Math.random() * this.farRight - 80)/40)*40)+20;
            while (randomX <= INIT_X) {
                randomX = (Math.round((Math.random() * this.farRight - 80)/40)*40)+20;
            }
            double randomY = (Math.round((Math.random() * this.farDown - 80) / 40) * 40) + 20;
            
            ArrayList<Integer> ab = new ArrayList<Integer>();
            
           
            
            if (squareOrEllipse <= .5) {
                barriers[a] = new Scenery("Square", new DCoords(randomX, randomY));
            } else if (squareOrEllipse > .5) {
                barriers[a] = new Scenery("Ellipse", new DCoords(randomX, randomY));
            }

        }
        for (int a = 0; a < numbers.length; a++) {
            double randomX = (Math.round((Math.random() * this.farRight - 80)/40)*40)+20;
            double randomY = (Math.round((Math.random() * this.farDown - 80)/40)*40)+20;
            double randomZ = (Math.round((Math.random() * this.farRight - 80)/40)*40)+20;
            double randomX2 = (Math.round((Math.random() * this.farRight - 80)/40)*40)+20;
            double randomY2 = (Math.round((Math.random() * this.farDown - 80)/40)*40)+20;
            double randomZ2 = (Math.round((Math.random() * this.farRight - 80)/40)*40)+20;
            CharaPath toss = new CharaPath(new Coords(randomX, randomY, randomZ), new Coords(randomX2, randomY2, randomZ2), currentUseUnit);
            toss.checkPath(currentUseUnit, barriers);
            while (toss.getPath().length > 50) {
                randomX2 = (Math.round((Math.random() * this.farRight - 80)/40)*40)+20;
                randomY2 = (Math.round((Math.random() * this.farDown - 80)/40)*40)+20;
                randomZ2 = (Math.round((Math.random() * this.farRight - 80)/40)*40)+20;
                toss = new CharaPath(new DCoords(randomX, randomY, randomZ), new DCoords(randomX2, randomY2, randomZ2), currentUseUnit);
                toss.checkPath(currentUseUnit, barriers);
            }
            numbers[a] = new Enemy(new DCoords(randomX, randomY, randomZ), "someEnemy: " + new Integer(a).toString(), new DCoords(randomX2, randomY2, randomZ2));
        }
        
    }
    
    void moveLocallyPart(int aX, int aY, int aZ){
       
        System.out.println("About to update with movement:");
        
        Coords tOrigin = this.currentUseUnit.placement.getOrigin();
//        
//        //TODO: Something to do with panel co-ordinates being taken to 
//        //normal grid co-ordinates.
//        
        double tX = 0.0;
        double tY = 0.0;
        double tZ = 0.0;
        //Determining which axis we ignore, and just copy that previous value over
        //But otherwise - we take the total movement in two axes and figure out 
        //the new location
        if(aZ == 0){
            tX = (aX + this.currentUseUnit.placement.getX());
            tY = (aY + this.currentUseUnit.placement.getY());
            tZ = this.currentUseUnit.placement.getZ();
        }else if(aZ == 1){
            tX = this.currentUseUnit.placement.getX();
            tY = (aY + this.currentUseUnit.placement.getY());
            tZ = (aX + this.currentUseUnit.placement.getZ());
        }
        
        this.currentUseUnit.placement.changeAll(new Coords(tX, tY, tZ, 1));
       
        this.roundGridPoint(this.currentUseUnit.placement);
        System.out.println("Updating:");
        this.setChanged();
        
        this.notifyObservers(currentUseUnit);
        System.out.println("Should be updated movement");
    }

    void rotateLocallyPart(int i, String z) {
        System.out.println("About to update:");
        this.currentUseUnit.placement.rotateLocallyPart(i, z);
        //Because the calculated point is possibly not directly aligned to grid, we'll round it
        //Until it is.
        this.roundGridPoint(this.currentUseUnit.placement);
        System.out.println("Updating:");
        this.setChanged();
        
        this.notifyObservers(currentUseUnit);
        System.out.println("Should be updated");
    }

    void rollback() {
        System.out.println("About to update:");
        this.currentUseUnit.placement.rollback();
        System.out.println("Updating:");
        this.setChanged();
        this.notifyObservers(currentUseUnit);
        System.out.println("Should be updated");
    }
    
    void roundGridPoint(Coords rounder){
        Coords flattened = rounder.flattenGlobal();
        double tx = flattened.getX();
        double ty = flattened.getY();
        double tz = flattened.getZ();
        System.out.println("Rounder X: " + (new Double(tx)).toString());
        System.out.println("Rounder Y: " + (new Double(ty)).toString());
        System.out.println("Rounder Z: " + (new Double(tz)).toString());
        //Essentially, we're trying to find the closest smaller multiplier to 40 for the number...
        //But then we need to offset by once it's multiplied by 40 to that location by 20.
        //Except to find out if it's negative or positive, we take the tx/ty/tz and figure out if
        //It's negative or not.
        tx = (double)((((int)(tx/40))*40));// + ((tx/tx)*20));
        ty = (double)((((int)(ty/40))*40));// +((ty/ty)*20));
        tz = (double)((((int)(tz/40))*40));// +((tz/tz)*20));
        System.out.println("Rounder NX: " + (new Double(tx)).toString());
        System.out.println("Rounder NY: " + (new Double(ty)).toString());
        System.out.println("Rounder NX: " + (new Double(tz)).toString());
        
        //Okay, now that we've flattened the Coords data and 
        //gotten it re-aligned to the grid, we need to 
        //re-orient it back to the origin of the Coords.
        
        Coords reOrient = rounder.getOrigin().flattenGlobal();
        
        tx = tx - reOrient.getX();
        ty = ty - reOrient.getY();
        tz = tz - reOrient.getZ();
        
        //Mostly done - now we just need to know whether to 
        //offset by +20 or -20
      
        //Tried putting that in the above initial offset, 
        //but it turns out...tx/tx isn't workable when tx = 0
        //Because of course you can't divide by 0.
//        if(tx >= 0){
            tx += 20;
//        }else{
//            tx += -20;
//        }
//        if(ty >= 0){
            ty += 20;
//        }else{
//            ty += -20;
//        }
//        if(tz >= 0){
            tz += 20;
//        }else{
//            tz += -20;
//        }
        System.out.println("Rounder CX: " + (new Double(tx)).toString());
        System.out.println("Rounder CY: " + (new Double(ty)).toString());
        System.out.println("Rounder CX: " + (new Double(tz)).toString());
        
        rounder.changeAll(new Coords(tx, ty, tz, rounder.getH()));
        System.out.println("Rounder FX: " + (new Double(rounder.getX())).toString());
        System.out.println("Rounder FY: " + (new Double(rounder.getY())).toString());
        System.out.println("Rounder FZ: " + (new Double(rounder.getZ())).toString());
    }
}
