using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace Ika.Graphics
{
    class OrbitCamera : Camera
    {
        class OrbitCameraControler : CameraControler
        {
            OrbitCamera m_camera;
            public OrbitCameraControler(OrbitCamera camera)
            {
                m_camera = camera;
            }

            protected override void MoveForward(float amount)
            {
                m_camera.Radius -= amount;
            }

            protected override void MoveUp(float amount)
            {
                m_camera.Polar += (float)MathHelper.ToRadians(amount);
            }

            protected override void MoveRight(float amount)
            {
                m_camera.Azimuth += (float)MathHelper.ToRadians(amount);
            }
        }

        float m_polar = 0.0f;
        /// <summary>
        /// Gets the polar angle of the camera
        /// </summary>
        public float Polar
        {
            get { return m_polar; }
            set { m_polar = value; EyeFromParams(); }
        }

        float m_azimuth = 0.0f;
        /// <summary>
        /// Gets the azimuth angle of the camera
        /// </summary>
        public float Azimuth
        {
            get { return m_azimuth; }
            set { m_azimuth = value; EyeFromParams(); }
        }

        float m_radius = 400.0f;
        /// <summary>
        /// Gets the radial position of the camera
        /// </summary>
        public float Radius
        {
            get { return m_radius; }
            set { m_radius = value; EyeFromParams(); }
        }

        public OrbitCamera()
        {
            Eye = Vector3.UnitX * -1;
            Target = Vector3.Zero;
            Up = Vector3.UnitZ;
        }

        public override void SetPointOfInterest(Vector3 point)
        {
            m_target = point;
            EyeFromParams();
        }

        protected void EyeFromParams()
        {
            if (m_polar > Math.PI / 2 - 0.001f)
            {
                m_polar = (float)Math.PI / 2 - 0.001f;
            }
            if (m_polar < -Math.PI / 2 + 0.001f)
            {
                m_polar = -(float)Math.PI / 2 + 0.001f;
            }
            if(m_radius < 1.0f)
            {
                m_radius = 1.0f;
            }

            Eye = new Vector3(Target.X + m_radius * (float)Math.Cos(m_azimuth) * (float)Math.Cos(m_polar),
                  Target.Y + m_radius * (float)Math.Sin(m_azimuth) * (float)Math.Cos(m_polar),
                  Target.Z + m_radius * (float)Math.Sin(m_polar));

            Up = new Vector3(0.0f, 0.0f, (float)Math.Cos(m_polar / 2.0));
        }

        protected override CameraControler CreateControler()
        {
            return new OrbitCameraControler(this);
        }
    }
}