package game;

import framework.animation.Animation3D;
import framework.gameMain.Actor;
import framework.gameMain.Movable;
import framework.gameMain.OvergroundActor;
import framework.model3D.BaseObject3D;
import framework.model3D.CollisionResult;
import framework.model3D.Object3D;
import framework.model3D.Placeable;
import framework.model3D.Position3D;
import framework.model3D.Quaternion3D;
import framework.physics.Force3D;
import framework.physics.Ground;
import framework.physics.PhysicsUtility;
import framework.physics.Solid3D;
import framework.physics.Velocity3D;
import java3d.Appearance;
import java3d.Box;
import java3d.Cylinder;
import java3d.Material;
import java3d.TransformGroup;
import java3d.Vector3d;

public class Laser implements Movable, Item {

	OvergroundActor actor;
	private boolean doesExist = false;
	private String state = null;
	boolean isCollision = false;
	
	public Laser(double x, double y, double z) {
				
		//レーザー生成
		Appearance ap1 = new Appearance();
		Material color = new Material();
		color.setEmissiveColor(1.0f, 1.0f, 0.0f);
		ap1.setMaterial(color);

		//円柱(レーザー)の大きさ
		Cylinder c1 = new Cylinder(1.0f, 30.0f, ap1);
		
		//円柱(レーザー)の配置、回転
		Object3D ob1 = new Object3D("lasersub", c1);
		ob1.apply(new Quaternion3D(1.0,0.0,0.0,Math.PI/2), false);

		Object3D ob2 = new Object3D("laser", new Object3D[]{ob1});		
		Solid3D laser = new Solid3D(ob2);
		
		//重力を消す
		actor = new OvergroundActor(laser,null) {
						
			@Override
			public Force3D getGravity() {
				return Force3D.ZERO;
			}
			//レーザーの当たり判定　→　反射
			@Override
			public void onIntersect(CollisionResult cr, long interval) {
//				System.out.println("OK");
//				calcMovelength(cr.normal.clone());	
//				Vector3d v = calcReflection(cr.normal);				
//				Velocity3D v2 = new Velocity3D(v);				
//				setVelocity(v2);
//				setDirection(v);
				
				setIsCollision(true);
				
			}			
		};
		
		
		
		actor.setInitialDirection(new Vector3d(0.0,0.0,-1.0));
	}
	
	//反射時、接触点へ移動させる計算
	public void calcMovelength (Vector3d n) {
		Vector3d pos = actor.getPosition().getVector3d();
		Vector3d v = actor.getDirection() ;
		double v1 ;
		v.normalize();
		v.scale(15);
		v1 = v.dot(n);		
		n.scale(-v1);
		v.add(n);
		v.scale(2);
		pos.add(v);
		actor.setPosition(new Position3D(pos));		
	}
	
	//反射の計算
	public Vector3d calcReflection(Vector3d normal) {
		Vector3d v = actor.getVelocity().getVector3d();
		normal.scale(2*v.dot(normal));
		v.sub(normal);
		return v;
	}
	
	@Override
	public TransformGroup getTransformGroupToPlace() {
		return actor.getTransformGroupToPlace();
	}

	@Override
	public BaseObject3D getBody() {
		return actor.getBody();
	}
	
	public void setInitialDirection(Vector3d v){
		actor.setInitialDirection(v);
	}
	
	public void setDirection(Vector3d dir) {
		actor.setDirection(dir);
	}

	public Vector3d getDirection() {
		return actor.getDirection();
	}
	
	public void setPosition(Position3D p){
		((Object3D)actor.getBody()).apply(p, false);
	}
	
	public double getX(){
		return actor.getPosition().getX();
	}
	
	public double getY(){
		return actor.getPosition().getY();
	}
	
	public double getZ(){
		return actor.getPosition().getZ();
	}
	
	public double getW(){
		return ((Object3D)actor.getBody()).getQuaternion().getW();
	}

	public void setVelocity(Velocity3D velocity3d) {
		actor.setVelocity(velocity3d);
	}
	
	public void setQuaternion(Quaternion3D q){
		((Object3D)actor.getBody()).apply(q, false);
	}

	//angel
	public double getAngle(){
		double angle;
		Vector3d getDir = actor.getDirection();
		Vector3d iniDir = actor.getInitialDirection().clone();
		getDir.normalize();
		double inner = getDir.dot(iniDir);
		Vector3d outerV = new Vector3d();
		outerV.cross(iniDir, getDir);
		double outer = outerV.dot(new Vector3d(0.0, 1.0, 0.0));
		angle = Math.atan2(outer, inner);
		return angle;
	}
	
	public void setAngle(double angle) {
		Vector3d initialDir = actor.getInitialDirection().clone();
		double x = initialDir.getZ()* Math.sin(angle) + initialDir.getX()*Math.cos(angle);
		double z = initialDir.getZ()* Math.cos(angle) - initialDir.getX()*Math.sin(angle);
		actor.setDirection(new Vector3d(x, 0.0, z));
	}
	
	public void setIsCollision(boolean isCollision){
		this.isCollision = isCollision;
	}
	
	public boolean getIsCollision(){
		return this.isCollision;
	}
	
	public boolean doesExist() {
		return doesExist;
	}

	public void setDoesExist(boolean doesExist) {
		this.doesExist = doesExist;
	}

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}

	@Override
	public void motion(long interval, Ground ground) {
		actor.motion(interval, ground);
	}
}
