using System;
using System.Collections.Generic;
using System.Text;

namespace GLUtils
{
    public class Vector3
    {
        private float theX, theY, theZ; // coordinates

        /// <summary>
        /// x component of the 3D vector
        /// </summary>
        public float X
        {
            get { return theX; }
            set { theX = value; }
        }

        /// <summary>
        /// y component of the 3D vector
        /// </summary>
        public float Y
        {
            get { return theY; }
            set { theY = value; }
        }

        /// <summary>
        /// z component of the 3D vector
        /// </summary>
        public float Z
        {
            get { return theZ; }
            set { theZ = value; }
        }

        /// <summary>
        /// Length of the 3D vector
        /// </summary>
        public float Abs
        {
            get { return (float)Math.Sqrt(theX * theX + theY * theY + theZ * theZ); }
        }
		
        /// <summary>
        /// Angle Theta of 3D vector
        /// </summary>
		public double Theta
		{
			get { return Math.Atan2(theZ, Math.Sqrt(theX*theX + theY*theY)); }
		}
		
        /// <summary>
        /// Angle Phi of the 3D vector
        /// </summary>
		public double Phi
		{
			get { return Math.Atan2(theY, theX) * Math.Cos(this.Theta); }
		}

        /// <summary>
        /// Creates 3D vector and initializes it with 0.0f, 0.0f, 0.0f
        /// </summary>
        public Vector3()
        {
            theX = theY = theZ = 0.0f;
        }

        /// <summary>
        /// Creates 3D vector and initializes it with x, y, z
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="z"></param>
        public Vector3(float x, float y, float z)
        {
            this.theX = x;
            this.theY = y;
            this.theZ = z;
        }

        /// <summary>
        /// Clones this 3D vector
        /// </summary>
        /// <returns></returns>
        public Vector3 Clone()
        {
            return new Vector3(theX, theY, theZ);
        }
		
        /// <summary>
        /// Returns string containing the vectors components
        /// </summary>
        /// <returns></returns>
		public override string ToString ()
		{
			return "(" + theX + ", " + theY + ", " + theZ + ")";
		}


        /// <summary>
        /// Add 3D vectors vector1 and vector2 component by component
        /// </summary>
        /// <param name="vector1"></param>
        /// <param name="vector2"></param>
        /// <returns></returns>
        public static Vector3 operator +(Vector3 vector1,Vector3 vector2)
        {
            return new Vector3(vector1.X + vector2.X, vector1.Y + vector2.Y, vector1.Z + vector2.theZ);
        }

        /// <summary>
        /// Subtracts 3D vector vector2 from 3D vector vector1 component by component
        /// </summary>
        /// <param name="vector1"></param>
        /// <param name="vector2"></param>
        /// <returns></returns>
        public static Vector3 operator -(Vector3 vector1, Vector3 vector2)
        {
            return new Vector3(vector1.X - vector2.X, vector1.Y - vector2.Y, vector1.Z - vector2.theZ);
        }

        /// <summary>
        /// Multiplies 3D vector with skalar (float)
        /// </summary>
        /// <param name="s"></param>
        /// <param name="vector"></param>
        /// <returns></returns>
        public static Vector3 operator *(float s, Vector3 vector)
        {
            return new Vector3(vector.X * s, vector.Y * s, vector.Z * s);
        }
    }
}
