package canvas.scene3d;

import script.Vector3;
import simphy.script.Matrix4;

/**
 * Camera to view Scene, the scene rendering depends only on following 3 attributes of camera
 * <ol>
 * <li>position: location of eye on camera, set by {@link #setPosition(Vector3)} </li>
 * <li>target: Always keeps its eye on target, i.e. renders target at center of viewport set by {@link #setTarget(Vector3)}</li>
 * <li>bank: the banking angle of Up direction of camera set by {@link #bank(Vector3)}</li>
 * </ol>
 * Note that local rotation and scaling of camera has no effect on rendering scene, because camera's UVN axes(View Matrix) is determined by eye, target and bank angle only
 * @author maheshkurmi
 */
public class Camera extends SceneNode3D{

	/**
	 * location of point in world space through which plane of projection passes, actually plane of projection or view
	 * plane is perpendicular to vector joining eye and focus and passes through focus. (Default value = (0,0,0))
	 */
	public Vector3 target = new Vector3();

	/**
	 * Sets the camera as orthographic camera 
	 * 
		 * @param verticalFov
		 *            Field of view of camera in Y direction
		 * @param aspect
		 *            width/height ratio used to calculate FOV in x direction
		 * @param near
		 *            distance of near plane from camera (must be >0)
		 * @param far
		 *            distance of far plane from camera	
		 * @return this camera
	 */
	public Camera setAsPerspective(double verticalFov, double aspect, double near, double far){
		return null;

	}
	
	/**
	 * Sets the camera as perspective camera 
	 * 
		 * @param verticalFOV
		 *            Field of view of camera in Y direction
		 * @param aspect
		 *            width/height ratio used to calculate FOV in x direction
		 * @param near
		 *            distance of near plane from camera (must be >0)
		 * @param far
		 *            distance of far plane from camera	
		 * @return this camera
	 */
	public Camera setAsOrthographic(double verticalFov, double aspect, double near, double far){
		return null;
	}
	
	/**
	 * Get whether this camera uses orthographic projection.
	 * 
	 * @return true if it does; false otherwise.
	 */
	public boolean isOrthographic() {
		return true;
	}

	/**
	 * Set whether this camera should use orthographic projection , all frustum parameters remain same
	 * 
	 * @param isOrthographic
	 *            true if it should; false otherwise.
	 */
	public void setOrthographic(boolean isOrthographic) {
		
	}
	
	/**
	 * Returns height of canvas screen height in pixel 
	 */
	public double getScreenHeight(){
		return 0;
	}
	
	/**
	 * Returns height of canvas screen width in pixel 
	 */
	public double getScreenWidth(){
		return 0;
	}
	
	
	/**
	 * Enables trackball
	 */
	public void setTrackBallEnabled(boolean enable){
		
	}
	
	/**
	 * Returns orbit controller for the camera
	 * @return {orbitControl}
	 */
	public OrbitControl getTrackBallController(){
		return null;
	}
	
	/**
	 * Sets position of Camera in world space
	 * 
	 * @param position
	 *            Position of camera (eye) in world coordinates
	 */
	public void setPosition(Vector3 position) {

	}


	/**
	 * Set position according relative to the parent's local coordinates
	 * 
	 * @param x
	 * @param y
	 * @param z
	 */
	public void setPosition(double x, double y, double z) {
	}
	
	/**
	 * Returns the target camera looking at
	 * @return {Vector3}
	 */
	public Vector3 getTarget(){
		return null;
	}
	
	/**
	 * Sets the target camera looking at
	 * 
	 * @param target
	 *            the point to look at in parents coordinates
	 */
	public void setTarget(Vector3 target) {

	}

	/**
	 * Sets the target camera looking at in parent coordinate
	 * 
	 * @param x
	 * @param y
	 * @param z
	 */
	public void setTarget(double x, double y, double z) {

	}
	
	/**
	 * Returns distance of Camera frustum near plane from camera 
	 * @return {number}
	 */
	public double getNear(){
		return 0;
	}
	
	/**
	 * Sets the distance of Camera frustum near plane from camera
	 * @param near
	 */
	public void setNear(double near){

	}
	
	/**
	 * Returns distance of Camera frustum far plane from camera 
	 * @return {number}
	 */
	public double getFar(){
		return 0;
	}
	
	/**
	 * Sets the distance of Camera frustum near plane from camera
	 * @param far
	 */
	public void setFar(double far){

	}
	
	/**
	 * Returns left plane of Camera frustum 
	 * @return {number}
	 */
	public double getLeft(){
		return 0;
	}
	
	/**
	 * Sets left plane  of Camera frustum 
	 * @param near
	 */
	public void setLeft(double left){

	}
	
	/**
	 * Returns right plane of Camera frustum 
	 * @return {number}
	 */
	public double getRight(){
		return 0;
	}
	
	/**
	 * Sets right plane  of Camera frustum 
	 * @param near
	 */
	public void setRight(double right){

	}
	
	/**
	 * Returns top plane of Camera frustum 
	 * @return {number}
	 */
	public double getTop(){
		return 0;
	}
	
	/**
	 * Sets top plane  of Camera frustum 
	 * @param near
	 */
	public void setTop(double top){

	}
	
	
	/**
	 * Returns bottom plane of Camera frustum 
	 * @return {number}
	 */
	public double getBottom(){
		return 0;
	}
	
	/**
	 * Sets bottom plane  of Camera frustum 
	 * @param near
	 */
	public void setBottom(double bottom){

	}
	
	/**
	 * Returns Camera frustum vertical field of view, from bottom to top of view, in degrees.
	 * @return {number}
	 */
	public double getFov(){
		return 0;
	}
	
	/**
	 * Sets Camera frustum vertical field of view, from bottom to top of view, in degrees.
	 * @param fov {Number} fov in degrees
	 */
	public void setFov(double fov){

	}
	
	/**
	 * Returns Camera frustum aspect ratio, usually the canvas width / canvas height
	 * @return {number}
	 */
	public double getAspect(){
		return 0;
	}
	
	/**
	 * Sets Camera frustum aspect ratio, usually the canvas width / canvas height
	 * @param aspect {Number} 
	 */
	public void setAspect(double aspect){
		
	}
	
	/**
	 * updates Camera View Matrix and physics for the camera node if any, also updates all its children if any <br>
	 * Must always be called every time before rendering scene
     * @param delta
     *            The time elapsed since the last scene update (in seconds)
     * @return true
     */
	public boolean update(final double dt){
		
		return true;
	}

	/**
	 * Get the current projection matrix-
	 * 
	 * @returns {Matrix4} a 4x4 projection matrix
	 */
	public Matrix4 getProjectionMatrix() {
		return null;
	}

	/**
	 * Get the current view matrix-
	 * 
	 * @returns {Matrix4} a 4x4 view matrix
	 */
	public Matrix4 getViewMatrix() {
		return null;
	}

	/**
	 * Get the current combined view projection matrix (=ProjectionMatrix*viewMatix)
	 * 
	 * @returns {Matrix4} a 4x4 viewProjection matrix
	 */
	public Matrix4 getViewProjectionMatrix() {
		return null;
	}

	/**
	 * Return the inverse current combined view projection matrix (=ProjectionMatrix*viewMatix), can be used to transform eye coordinates to world coordinates
	 * 
	 * @returns {Matrix4} a 4x4 viewProjection matrix
	 */
	public Matrix4 getInverseViewProjectionMatrix() {
		return null;
	}

	/**
	 * Get 3 vectors representing the UVN axes of this camera in order.
	 * 
	 * @return an array of 3 vectors.
	 */
	public Vector3[] getCameraUVNAxes() {
		return null;
	}

	

	/**
	 * Rotate the camera around Axis in World space.
	 * 
	 * @param the
	 *            3D rotation angles (in Degrees).
	 * 
	 */
	public void rotateAboutAxes(double theta_x, double theta_y, double theta_z) {

		
	}

	/**
	 * Rotate the camera around its focal point.
	 * 
	 * @param ya
	 *            : angle to be rotated about U axis (in degrees).
	 * @param pitch
	 *            : angle to be rotated about N axis (in degrees).
	 * @param roll
	 *            : angle to be rotated about V axis (in degrees).
	 * 
	 */
	public void rotateAroundFocus(double ya, double pitch, double roll) {
		
	}

	/**
	 * Translate the camera in World space in such a way the projection on view Plane translates accordingly. It is
	 * achieved by translating eye(camera position) as well as focus by x and y along U and V axis (in world space)
	 * respectively.
	 * 
	 * @param x
	 *            Amount camera translates along its right (U axis).
	 * @param y
	 *            Amount camera translates along its up (V axis)
	 */
	public void pan(double dx, double dy) {
		
	}
	
	
	

	/**
	 * Banks camera,or we can say rolls cameras UP vector clockwise, so that the projection on view Plane seems to be
	 * rotating about a line joining focus and eye(N Vector).
	 * 
	 * @param theta
	 *            the angle in Degrees by which camera UP vector rotates clockwise.
	 */
	public void bank(double theta) {
		
	}
	
	
	/** Function to translate a point given in screen coordinates to world space. It's the same as GLU gluUnProject, but does not
	 * rely on OpenGL. The x- and y-coordinate of vec are assumed to be in screen coordinates (origin is the top left corner, y
	 * pointing down, x pointing to the right) as reported by the touch methods in {@link Input}. A z-coordinate of 0 will return a
	 * point on the near plane, a z-coordinate of 1 will return a point on the far plane. This method allows you to specify the
	 * viewport position and dimensions in the coordinate system expected by {@link GL20#glViewport(int, int, int, int)}, with the
	 * origin in the bottom left corner of the screen.
	 * @param screenCoords the point in screen coordinates (origin top left)
	 * @param viewportX the coordinate of the bottom left corner of the viewport in glViewport coordinates.
	 * @param viewportY the coordinate of the bottom left corner of the viewport in glViewport coordinates.
	 * @param viewportWidth the width of the viewport in pixels
	 * @param viewportHeight the height of the viewport in pixels
	 * @return the mutated and unprojected screenCoords {@link Vector3} */
	public Vector3 unproject (Vector3 screenCoords, double viewportX, double viewportY, double viewportWidth, double viewportHeight) {
	
		return null;
	}

	/** Function to translate a point given in screen coordinates to world space. It's the same as GLU gluUnProject but does not
	 * rely on OpenGL. The viewport is assumed to span the whole screen and is fetched from {@link Graphics#getWidth()} and
	 * {@link Graphics#getHeight()}. The x- and y-coordinate of vec are assumed to be in screen coordinates (origin is the top left
	 * corner, y pointing down, x pointing to the right) as reported by the touch methods in {@link Input}. A z-coordinate of 0
	 * will return a point on the near plane, a z-coordinate of 1 will return a point on the far plane.
	 * @param screenCoords the point in screen coordinates
	 * @return the mutated and unprojected screenCoords {@link Vector3} */
	public Vector3 unproject (Vector3 screenCoords) {
		return null;

	}

	/** Projects the {@link Vector3} given in world space to screen coordinates. It's the same as GLU gluProject with one small
	 * deviation: The viewport is assumed to span the whole screen. The screen coordinate system has its origin in the
	 * <b>bottom</b> left, with the y-axis pointing <b>upwards</b> and the x-axis pointing to the right. This makes it easily
	 * useable in conjunction with {@link Batch} and similar classes.
	 * @return the mutated and projected worldCoords {@link Vector3} */
	public Vector3 project (Vector3 worldCoords) {
		return null;

	}

	/** Projects the {@link Vector3} given in world space to screen coordinates. It's the same as GLU gluProject with one small
	 * deviation: The viewport is assumed to span the whole screen. The screen coordinate system has its origin in the
	 * <b>bottom</b> left, with the y-axis pointing <b>upwards</b> and the x-axis pointing to the right. This makes it easily
	 * useable in conjunction with {@link Batch} and similar classes. This method allows you to specify the viewport position and
	 * dimensions in the coordinate system expected by {@link GL20#glViewport(int, int, int, int)}, with the origin in the bottom
	 * left corner of the screen.
	 * @param viewportX the coordinate of the bottom left corner of the viewport in glViewport coordinates.
	 * @param viewportY the coordinate of the bottom left corner of the viewport in glViewport coordinates.
	 * @param viewportWidth the width of the viewport in pixels
	 * @param viewportHeight the height of the viewport in pixels
	 * @return the mutated and projected worldCoords {@link Vector3} */
	public Vector3 project (Vector3 worldCoords, double viewportX, double viewportY, double viewportWidth, double viewportHeight) {
		return null;

	}
	

	/**
	 * Sets this camera as replica of specified camera <br>
	 * Note that only camera related properties are copied not scenegraph related like parent and children
	 * @param {Camera} camera
	 * @return this camera
	 */
	public Camera set(Camera camera){
		return null;

	}
	
	/**
	 * Clones this node Note that Model is not cloned, only its reference is copied
	 */
	public Camera clone() {
		return null;

	}


}