/*
 * May not be fully implemented. Not tested in worldserver3D.
 */
package model;

import motorcontrol.CarLikeCreatureKinematics;
import java.awt.Color;
import java.awt.Graphics2D;
import java.io.IOException;
import util.Constants;

/**
 *
 * @author eccastro
 */
public class OldCarCreature extends Creature {


protected double x; //compile only
protected double y; //compile only


//from previous car-like 2D model (not currently in use in 3D simulator):
    private int crossedScreen = 0;
    private final double SIZE = 50.0;
    private final double WIDTH = 0.43 * SIZE;
    private final double LENGTH = 0.43 * SIZE;
    private final double AXLES = 0.49 * SIZE;
    private double zoom;
    private final double POINT_DISTANCE = 0.35 * SIZE;
    private final double POINT_SIZE = 0.1 * SIZE;
    private double vsSquareX;
    private double vsSquareY;
    private final double VS_DISTANCE_MIN = 10.0;
    private final double VS_DISTANCE_MAX = 150.0;
    private final double VS_ANGLE_MIN = -60.0;
    private final double VS_ANGLE_MAX = 60.0;
    private double vsDistance;
    private double vsAngle;
    private final int VS_NSQUARES = 8;
    private final int VS_PERIOD = 0;
    private int vsCounter;
    private final double CS_SIZE = 7.0;
    private Sensor visualSensors[][];

    protected double friction;
    public OldCarCreature(double initialX, double initialY, double iPitch, Environment env) {

        super(initialX, initialY, iPitch, env);
        kinematics = new CarLikeCreatureKinematics(this);

        friction = 0.0;
        try {
             sf = new ThingShapeFactory(" path to a car image: .gif or .3ds etc", this);
            //shape = this.getNode(sf);
        } catch (IOException ex) {
            System.out.println("!!!!!Creature: Erro ! ");
            ex.printStackTrace();
        }


        zoom = 1.0;

        /* Initialize visual sensors */
        visualSensors = new Sensor[VS_NSQUARES][VS_NSQUARES];
        for (int i = 0; i < VS_NSQUARES; ++i) {
            for (int j = 0; j < VS_NSQUARES; ++j) {
                visualSensors[i][j] = new Sensor();
            }
        }
        vsAngle = (VS_ANGLE_MIN + VS_ANGLE_MAX) / 2;
        vsDistance = (VS_DISTANCE_MIN + VS_DISTANCE_MAX) / 2;
        vsCounter = 0;
        updateVisualSensorPosition();

    }

    public double getFriction() { return friction; }
    public void setFriction(double friction) { this.friction = friction; }
    
    public double getSize() {
        return SIZE;
    }

    public double getWidth() {
        return WIDTH;
    }

    public double getLength() {
        return LENGTH;
    }

    public double getAxles() {
        return AXLES;
    }

    public double getZoom() {
        return zoom;
    }

    public int getVSNSquares() {
        return VS_NSQUARES;
    }

    public int getVSCounter() {
        return vsCounter;
    }

    public double getVSDistance() {
        return vsDistance;
    }

    public double getVSAngle() {
        return vsAngle;
    }

    public Sensor getVisualSensor(int i, int j) {
        return visualSensors[i][j];
    }

    public void setVSCounter(int vsCounter) {
        this.vsCounter = vsCounter;
    }

    public synchronized void setZoom(double zoom) {
        this.zoom = zoom;

        updateContactSensorPosition();
        updateVisualSensorPosition();
    }

    public synchronized void setVSDistance(double vsDistance) {
        this.vsDistance = vsDistance;

        updateVisualSensorPosition();
    }

    public synchronized void setVSAngle(double vsAngle) {
        this.vsAngle = vsAngle;

        updateVisualSensorPosition();
    }

    //TODO: compare with old version in 2D model. May be not fully implemented here.
    public Color getVSColor(int i, int j) {
        return (Color) ((visualSensors[i][j].getMaterial() != null) ? visualSensors[i][j].getMaterial().getColor() : Color.white);
    }

    public boolean pointContains(double pointX, double pointY) {
        return (Math.abs(x + zoom * POINT_DISTANCE * Math.cos(Math.toRadians(pitch)) - pointX) < zoom * POINT_SIZE / 2 &&
                Math.abs(y + zoom * POINT_DISTANCE * Math.sin(Math.toRadians(pitch)) - pointY) < zoom * POINT_SIZE / 2)
                ? true : false;
    }

    public int hasCrossedTheScreen() {
        int r = crossedScreen;
        crossedScreen = 0;
        return r;
    }

    public void updateContactSensorPosition() {
        double x0 = -zoom * LENGTH / 2, y0 = -zoom * WIDTH / 2;
        double x1 = +zoom * LENGTH / 2, y1 = +zoom * WIDTH / 2;

        // Coordenandas dos sensores antes da rota��o
        // sensor0 = (x0,y0); sensor1 = (x1,y0); sensor2 = (x1,y1); sensor3 = (x0,y1)

        // Rota��o o ponto
        double cosPitch = Math.cos(Math.toRadians(pitch));
        double sinPitch = Math.sin(Math.toRadians(pitch));

        contactSensors[0].setX(x + x0 * cosPitch - y0 * sinPitch);
        contactSensors[0].setY(y + x0 * sinPitch + y0 * cosPitch);
        contactSensors[1].setX(x + x1 * cosPitch - y0 * sinPitch);
        contactSensors[1].setY(y + x1 * sinPitch + y0 * cosPitch);
        contactSensors[2].setX(x + x1 * cosPitch - y1 * sinPitch);
        contactSensors[2].setY(y + x1 * sinPitch + y1 * cosPitch);
        contactSensors[3].setX(x + x0 * cosPitch - y1 * sinPitch);
        contactSensors[3].setY(y + x0 * sinPitch + y1 * cosPitch);
    }

    void drawPointContour(Graphics2D g2D) {
        g2D.setColor(Color.black);
        g2D.drawOval((int) (x + zoom * (POINT_DISTANCE * Math.cos(Math.toRadians(pitch)) - POINT_SIZE / 2)),
                (int) (y + zoom * (POINT_DISTANCE * Math.sin(Math.toRadians(pitch)) - POINT_SIZE / 2)),
                (int) (zoom * POINT_SIZE), (int) (zoom * POINT_SIZE));
    }

    @Override
    public void updateMyPosition() {
        this.kinematics.updatePosition();
    }

    public synchronized void move(double dTime, Environment e)
	{
		/***********FUEL*************/
		double deltaFuel = 0;
		for (int i = 0; i < 4; ++i)
			if (contactSensors[i].getMaterial() != null)
				deltaFuel += contactSensors[i].getMaterial().getEnergy();
			deltaFuel /= 4;

		//Enche mais r�pido quando "parar" para abastecer
		if (speed == 0)
			deltaFuel *= 15;

		//deltaFuel /= 400;//<----------

		//fuel += (-1E-5+1E-2*deltaFuel)*1000;
		fuel += -0.1 + deltaFuel;
		if (fuel > Constants.CREATURE_MAX_FUEL) fuel = Constants.CREATURE_MAX_FUEL;
		if (fuel < 0)        fuel = 0;

		//System.out.println("fuel: "+ fuel);
		setChanged();
		notifyObservers();

	    /***********FRICTION***********/
		if (speed >= 0)
		{
		    double hardness1 = 0.0;
            double hardness2 = 0.0;

            if (contactSensors[1].getMaterial() != null) {
                hardness1 = contactSensors[1].getThing().getHardness();
                if (hardness1 == 0.0) {
                    if (checkIfHidden(contactSensors[1].getThing())) {
                        handleHiddenObstacleDetection(contactSensors[1].getThing());
                    }
                }
            }
            if (contactSensors[2].getMaterial() != null) {
                hardness2 = contactSensors[2].getThing().getHardness();
                if (hardness2 == 0.0) {
                    if (checkIfHidden(contactSensors[2].getThing())) {
                        handleHiddenObstacleDetection(contactSensors[2].getThing());
                    }
                }
            }
            //System.out.println("----- hardness1= "+hardness1+" hardness2= "+hardness2);
             //friction = (hardness1 > hardness2) ? hardness1 : hardness2;
            if (hardness1 > hardness2){
                friction = hardness1;
                if (friction > 0){
                 handleCollision(contactSensors[1].getThing());
             }
            }else{
                friction = hardness2;
                if (friction > 0){
                 handleCollision(contactSensors[2].getThing());
                }
            }

		}
		else
		{
			double hardness3 = 0.0;
			double hardness0 = 0.0;

			if (contactSensors[3].getMaterial() != null) hardness3 = contactSensors[3].getThing().getHardness();
			if (contactSensors[0].getMaterial() != null) hardness0 = contactSensors[0].getThing().getHardness();

			friction = (hardness3 > hardness0) ? hardness3 : hardness0;
		}

		/********************************/
                if (getFuel() > 0) {

                    //this.kinematics.updatePositionData();
                    updateMyPosition();

                }
//		if      (x > e.width) {
//			x = 0;
//			crossedScreen = 2;   //direita
//
//		}
//		else if (x < 0) {
//			x = e.width;
//			crossedScreen = 1;   //esquerda
//		}
//
//		if      (y > e.height) {
//			y = 0;
//			crossedScreen = 4;   //em cima
//		}
//		else if (y < 0) {
//			y = e.height;
//			crossedScreen = 3;  //em baixo
//		}

        if (x > e.width)
			x = e.width;
		if (x < 0)
			x = 0;
		if (y > e.height)
			y = e.height;
		if (y < 0)
			y = 0;

		updateContactSensor(e);
		updateVisualSensor (e);

		setChanged();
		notifyObservers();
	}

    @Override
    public Knapsack putMeInKnapsack(Knapsack sack) {
        throw new UnsupportedOperationException("Makes no sense for my type of Thing!!!");
    }

    @Override
    public void setID(Long id, Environment e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void updateShape(String model, float scale, Environment e) {
        throw new UnsupportedOperationException("This type of Thing does not support this operation yet");
    }
	
}
