/*******************************************************************************
*Redistribution and use in source and binary forms are prohibited without 
*express written permission from Bill Tomlinson.  Please contact him 
*(wmt@uci.edu) for more information.  
*
*THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS "AS IS" AND ANY 
*EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
*WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
*DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY 
*DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
*(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
*ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
*(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
*THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*All rights reserved.

*Copyright (c) 2003 MASSACHUSETTS INSTITUTE OF TECHNOLOGY and Bill Tomlinson
*******************************************************************************/
package content.ac;

import java.util.List;

import research.PhysicalObject;
import research.motor.*;
import innards.math.linalg.*;
import innards.signal.provider.ConstantDoubleProvider;
import research.basics.*;
import pc.research.device.keyboard.Keyboard;
import pc.ui.UtilitySlider;

/**
 * @author Bill Tomlinson
 *
 */
public class User extends Person implements acePerson {

	/** Fields */

	/** Constructor */
	public User(String name) {
		super(name, "geometry/person.x");
		//super(name, "geometry/personInvisible.x");
	}

	public void setUpShading(String color) {
		double red = 0.0;
		double green = 0.5;
		double blue = 1.0;
		this.getGeometry().getMaterial().setAmbientColor(red, green, blue);
	}

	/** Methods */
	boolean inhibitGiving = false;
	Vec3 myPos = new Vec3();	
	Vec3 spotInFrontOfMe = new Vec3();	
	int inhibitGivingTimer = 0;
	int waitingToDoActionTimer = 0;
	//The update method gets executed once per time step 
	//It does the bulk of the work of deciding what the Person is going to do.
	public void update(double time) {

		super.update(time);
		Keyboard k = new Keyboard();
		System.out.println("Keyboard in: "+k.getKeyID());

		if (waitingToDoActionTimer > 0) {
			waitingToDoActionTimer--;
		} else {
			action = "STAND";
		}
		if (inhibitGivingTimer > 0) {
			inhibitGivingTimer--;
			inhibitGiving = true;
		} else {
			inhibitGiving = false;
		}

		System.out.println("inhibitGivingTimer "+inhibitGivingTimer);
		if (k.hasNewData() && k.getKeyID() == 87) {
			action = "WALK_STRAIGHT";
			waitingToDoActionTimer = 11;
		}
		if (k.hasNewData() && k.getKeyID() == 90) {
			action = "STEP_BACK";
			waitingToDoActionTimer = 11;
		}
		if (k.hasNewData() && k.getKeyID() == 65) {
			action = "TURN_LEFT";
			waitingToDoActionTimer = 11;
		}
		if (k.hasNewData() && k.getKeyID() == 68) {
			action = "TURN_RIGHT";
			waitingToDoActionTimer = 11;
		}
		if (k.hasNewData() && k.getKeyID() == 71  && !inhibitGiving) {
			//go through all the characters.  find the one closest
			acePerson closest = null;
			double distance = 100000;//very far away
			List all = research.World.getWorld().getCreatures();
			for (int i = 0; i < all.size(); i++)
			{
				if (all.get(i)!= this)
				{
					myPos = this.getPosition();
					this.localVecToWorldVec(
						PhysicalObject.LOCALSPACE_FORWARD,
						spotInFrontOfMe);
					//make it bigger
					spotInFrontOfMe.scale(30);
					Vec3.add(myPos, spotInFrontOfMe, spotInFrontOfMe);
					//content.ac.Demo.mrCube.setPosition(spotInFrontOfMe);
					Vec3.sub(((acePerson)all.get(i)).getPosition(), spotInFrontOfMe, difference);
					if (difference.mag() < distance)
					{
						closest = ((acePerson)all.get(i));
						distance = difference.mag();
					}
				}
			}
			if (closest != null)
//			closest.receive(this);
			SoundSystem.play("w:/sound/money.wav");
			for(int i = 0; i < 10; i++)System.out.println("USER GIVING!");
			inhibitGivingTimer = 10;
			System.out.println("yourCharacter.getOrientation = "+closest.getOrientation());
			System.out.println("yourCharacter.getPosition = "+closest.getPosition());
			System.out.println("yourCharacter.getEmotion = "+closest.getEmotion());
			System.out.println("yourCharacter.getActivity = "+closest.getActivity());
			System.out.println("yourCharacter.getCharacterType = "+closest.getCharacterType());
			System.out.println("yourCharacter.getCharacterID = "+closest.getCharacterID());
			closest.receive(this);
			System.out.println("If you can read this line, your character did not crash when I called receive on it.  Congratulations!");
			}

		k.notifyDataRead();
		memory.write(
			0.0,
			"HAPPINESS",
			new ConstantDoubleProvider(1.0),
			this.getName());
		//System.out.println("ACtion = "+action);
		memory.write(0.0, MotorActionGroup.MOTOR_DESIRED, action, "self");
	}
	//get character's orientation in world coords, polar coords
	public double getOrientation() {
		return 0;
	}
	Vec3 pos = new Vec3();
	Vec3 difference = new Vec3();
	//get Position in ACEunits, Z is up
	public Vec3 getPosition() {
		this.getPosition(pos);
		return pos;
	}
	//get character's emotional state, three values from 0 to 1, pleasure = x, arousal = y, TBD = z
	public Vec3 getEmotion() {
		return new Vec3();
	}
	//get character's activity (see above for possibilities)
	public int getActivity() {
		return acePerson.ACTIVITY1;
	}
	//get character's type ("ace_02", "ace_05", etc.)
	public int getCharacterType() {
		return acePerson.USER;
	}
	//not sure about character IDs format
	public int getCharacterID() {
		return myID;
	}

	//you promise to take one coin out of your bank account 
	//every time you call receive on someone else
	public void receive(Person giver) {
		return;
	}
}