using Microsoft.Xna.Framework;

namespace KavTest
{
    public struct ArcballTransform
    {
        public Vector3 Position { get; }
        public float Yaw { get; }
        public float Pitch { get; }

        private Matrix RotationMatrix { get; }
        public Matrix TransformMatrix { get; }
        public Vector3 Forward { get { return TransformMatrix.Forward; } }
        public Vector3 Right { get { return TransformMatrix.Right; } }
        public Vector3 Up { get { return TransformMatrix.Up; } }

        public ArcballTransform(Vector3 position, float yaw, float pitch)
        {
            Position = position;
            Yaw = yaw;
            Pitch = pitch;
            RotationMatrix = CreateRotationMatrix(Yaw, Pitch);
            TransformMatrix = CreateTransformMatrix(Position, RotationMatrix);
        }

        public ArcballTransform RotateLocal(float deltaYaw, float deltaPitch)
        {
            var newPitch = MathHelper.Clamp(Pitch + deltaPitch, -Microsoft.Xna.Framework.MathHelper.PiOver2, Microsoft.Xna.Framework.MathHelper.PiOver2);
            return new ArcballTransform(Position, Yaw + deltaYaw, newPitch);
        }

        public ArcballTransform TranslateLocal(Vector3 localTranslation)
        {
            var worldTranslation = Vector3.Transform(localTranslation, RotationMatrix);
            return new ArcballTransform(Position + worldTranslation, Yaw, Pitch);
        }

        private static Matrix CreateRotationMatrix(float yaw, float pitch)
        {
            return
                Matrix.CreateRotationX(pitch) *
                Matrix.CreateRotationY(yaw);
        }

        private static Matrix CreateTransformMatrix(Vector3 position, Matrix rotation)
        {
            return
                rotation *
                Matrix.CreateTranslation(position);
        }
    }
}
