namespace DarkWynter.Engine.GameObjects
{
    #region Using Statements
    using System;
    using System.Collections.Generic;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Audio;
    using Microsoft.Xna.Framework.Content;
    using Microsoft.Xna.Framework.Graphics;
    using Microsoft.Xna.Framework.Input;
    using Microsoft.Xna.Framework.Storage;
    using ObjectLib;
    using Globals;
    using Init;
    using DarkWynter.Stream;
    #endregion

    /// <summary>
    /// A Billboard Sprite places a Texture in 3D space that is always oriented towards the user.
    /// This makes an effective tool to do lightweight props such as brush, clouds, smoke, or fire.
    /// GameObjects cann add Billboards to ObjectLibrary's BillboardList in the Draw_Billboards method.
    /// </summary>
    public class Billboard : GameObject
    {
        /// <summary>
        /// Offset Position of the Sprite
        /// </summary>
        public Vector3 offset;

        /// <summary>
        /// Width of the Billboard
        /// </summary>
        public float width;

        /// <summary>
        /// Height of the Billboard
        /// </summary>
        public float height;

        public Billboard(Load gameObjectLoader)
            : base(gameObjectLoader)
        {

        }
        /// <summary>
        /// Create a Billboard Object with it's own texture
        /// </summary>
        /// <param name="Position">Location of the Billboard in 3D space.</param>
        /// <param name="Offset">Position relative to CurrentPosition, used to modulate motion.</param>        
        /// <param name="Width">Width of the Billboard.</param>
        /// <param name="Height">Height of the Billboard.</param>
        /// <param name="Image">Texture to use with this Billboard.</param>
        public void Load(Vector3 Position, Vector3 Offset, float Width, float Height, Texture2D Image)
        {
            this.draw = new Draw(Enums_Stream.DrawMethod.BillBoards_Draw, "DrawQuad");
            this.draw.model = Statics_Engine.SystemSettings.content.Load<Model>("Content/_models/GenericQuad");
            foreach (ModelMesh mesh in this.draw.model.Meshes)
            {
                for (int i = 0; i < mesh.MeshParts.Count; i++)
                {
                    // Add effect to mesh
                    mesh.MeshParts[i].Effect = ShaderParameters.DrawFX.effect;
                }
            }

            this.mass.currentPosition = Position;
            this.offset = Offset;
            this.draw.textureList.Add(Image);
            this.width = Width;
            this.height = Height;
        }

        /// <summary>
        /// Sets the current position of the billboard
        /// </summary>
        /// <param name="position">The new Vector3 position of the billboard</param>
        public Vector3 Position
        {
            get
            {
                return this.mass.currentPosition;
            }
            set
            {
                this.mass.currentPosition = value;
            }
        }

        /// <summary>
        /// Sets the current position of the billboard
        /// </summary>
        /// <param name="position">The new Vector3 position of the billboard</param>
        public void SetTexture(Texture2D texture)
        {
            this.draw.textureList.Clear();
            this.draw.textureList.Add(texture);

        }

        /// <summary>
        /// Set the draw location relative to the current position.
        /// Makes it easy to create jitter, rotation, or other simple animations without effecting currentPosition.
        /// </summary>
        /// <param name="locationOffset"></param>
        public void SetOffset(Vector3 locationOffset)
        {
            this.offset = locationOffset;
        }

        /// <summary>
        /// Draws the current billboard
        /// </summary>
        /// <param name="objectLibrary">ObjectLibrary</param>
        /// <param name="playerIndex">The index of the current player whose view is being drawn (for orienting the billboard)</param>
        public Draw Draw_Billboards(ObjectLibrary objectLibrary, int playerIndex)
        {
            // Combine current and offset positions
            Vector3 billboardPosition = this.mass.currentPosition + this.offset;

            // Face Billboard Towards The Camera
            this.draw.matrix = Matrix.CreateTranslation(new Vector3(-0.5f, -0.5f, -0.5f)) *
                          Matrix.CreateScale(new Vector3(this.width, this.height, 0.0f)) *
                          Matrix.CreateBillboard(billboardPosition,
                                                 objectLibrary.humans[playerIndex].mass.currentPosition,
                                                 objectLibrary.humans[playerIndex].mass.upVector,
                                                 objectLibrary.humans[playerIndex].mass.normalVector);

            return this.draw;
        }
    }
}