//---------------------------------------------------------------------------------------------------------------------------------------------------
// <copyright file="Portal.cs" company="DarkWynter Studios">
//     Copyright (C)2007 DarkWynter Studios.  All rights reserved.
// </copyright>
//---------------------------------------------------------------------------------------------------------------------------------------------------
// {Contact : darkwynter.com for licensing information
//---------------------------------------------------------------------------------------------------------------------------------------------------

namespace DarkWynter.Game.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 System.Xml;
    #endregion

    using DarkWynter.Engine.Globals;
    using DarkWynter.Engine.Physics;
    using DarkWynter.Engine.ObjectLib;
    using DarkWynter.Engine.GameObjects;
    using DarkWynter.Engine.Init;
    using DarkWynter.Stream;


    /// <summary>
    /// An abstract door with locking mechanics.
    /// </summary>
    public class Portal : GameObject
    {
        private int portalID;
        private int health;
        private bool isLocked = true;
        private int fireIterator = 0;

        /// <summary>
        /// Portal constructor
        /// </summary>
        public Portal(Load gameObjectLoader)
            : base(gameObjectLoader)
        {
            mass.objectType = Enums_Engine.ObjectType.PORTAL;
            mass.dynamicFrictionCoefficient = 0.0f;
            mass.isMoving = true;
        }

        /// <summary>
        /// Override and supplament base loading in GameObject.
        /// </summary>
        /// <param name="node">XML node containing load data.</param>
        /// <param name="objectLibrary">ObjectLibrary that portal belongs to.</param>
        /// <returns>True if it was able to load, else false</returns>
        public override bool Load(ObjectLibrary objectLibrary)
        {
            // Call before user code is executed
            if (!base.Load(objectLibrary))
            {
                return false;
            }

            draw.drawMethod = Enums_Stream.DrawMethod.BasicGameObject_Draw;
            draw.technique = "BasicLightingShaderMain";

            //mass.boundingVolume = new BoundingVolume(new BoundingBox(mass.currentPosition - mass.scale, mass.currentPosition + mass.scale));
            mass.boundingVolume = new BoundingVolume(new BoundingSphere(mass.currentPosition, 100.0f));

            draw.textureList.Add(Statics_Engine.SystemSettings.content.Load<Texture2D>("Content/_textures/FireRed"));
            //draw.textureList.Add(Statics_Engine.SystemSettings.content.Load<Texture2D>("Content/_textures/FireDesert"));
            draw.textureList.Add(Statics_Engine.SystemSettings.content.Load<Texture2D>("Content/_textures/FireBlue"));
            draw.textureList.Add(Statics_Engine.SystemSettings.content.Load<Texture2D>("Content/_textures/FireAir"));

            // Xml Parameters specific to object
            health = int.Parse(load.node.Attributes["portalHealth"].Value);
            return true;
        }

        /// <summary>
        /// Override and supplement base Update in GameObject.
        /// </summary>
        /// <param name="objectLibrary">ObjectLibrary that portal belongs to.</param>
        public override void Update(ref ObjectLibrary objectLibrary)
        {
            // Call before user code is executed
            base.Update(ref objectLibrary);

            // Update Collision Box : CLEAN : SCALE SHOULD BE 3 VALUES IN XML
            //mass.boundingVolume.UpdateBox(mass.currentPosition, mass.currentRotation, mass.scale * new Vector3(20.0f, 1000.0f, 1000.0f));
            
            mass.boundingVolume.UpdateSphere(mass.currentPosition);
            
            // Fun with doors...
            //mass.Rotate(0.0f, 0.01f);
            //mass.AddForce(new Vector3(-10.0f, 0.0f, 0.0f));
        }

        /// <summary>
        /// Override and supplement response to colliding GameObjects
        /// </summary>
        /// <param name="collidedObject">Object that hit the Portal.</param>
        /// <param name="resultantForce">Force that Portal was hit with.</param>
        /// <param name="objectLibrary">ObjectLibrary that portal belongs to.</param>
        /// <returns>True if collidedObject needs to be recycled</returns>
        public override bool ObjectCollisionResponse(GameObject collidedObject, Vector3 resultantForce, ObjectLibrary objectLibrary)
        {

                if (collidedObject.mass.objectType != Enums_Engine.ObjectType.PLAYER)
                {
                    // Non-playerObject - Non-playerObject collision response
                    if (health == 0)
                    {
                        mass.AddForce(new Vector3(0.0f, -1000.0f, 0.0f));
                    }
                    else
                    {
                        health--;
                    }
                }
                if (collidedObject.mass.objectType == Enums_Engine.ObjectType.PLAYER)
                {
                    // if human, load next room
                    // if islocked = true, rotate door model open
                    // else, remain shut

                    // HACK: BreakPoint for dev...
                    health--;
                    health++;
                }

                switch (portalID)
                {
                    case 1:
                        // Call the method for the door
                        //if (collidedObject.mass.objectType == Mass.ElementType.EARTH)
                            //Door can take damage
                            //portalHealth = portalHealth - totalDamage(); 
                        //}
                        if (health <= 0)
                        {    // Call the doop open method

                            //Drop the collision detection
                            mass.boundingVolume.UpdateBox(mass.currentPosition, mass.currentRotation, Vector3.Zero);
                        }
                        break;

                    case 2:
                        // Call the method for the door
                        break;

                }

                if (isLocked == false)
                {
                    //Rotate door model open
                }

            return false;
        }


        /// <summary>
        /// Overrides and supplements response to this object hitting the ground.
        /// </summary>
        /// <param name="terrain">The terrain object which this Portal hit.</param>
        public override void TerrainCollisionResponse(Terrain terrain)
        {
            base.GetObjectHeight(terrain);

            // Add Gravity if terrain and player are touching
            if (heightDifference < 0.0f)
            {
                mass.AddForce(mass.mass * Statics_Engine.GameSettings.accelDueToGravity);
            }
            else if (heightDifference > 0.0f)
            {
                base.TerrainCollisionResponse(terrain);

                if (mass.totalForce.Y > 0.0f)
                {
                    mass.totalForce.Y = 0.0f;
                }

                if (mass.velocity.Y > 0.0f)
                {
                    mass.velocity.Y = 0.0f;
                }

                if (heightDifference < 0.0f)
                {
                    mass.AddForce(mass.mass * Statics_Engine.GameSettings.accelDueToGravity);
                }
                else if (heightDifference > 0.0f)
                {
                    if (mass.totalForce.Y > 0.0f) { mass.totalForce.Y = 0.0f; }
                    if (mass.velocity.Y > 0.0f) { mass.velocity.Y = 0.0f; }

                    // Ground pushing up to negate gravity
                    mass.AddForce(new Vector3(0.0f, heightDifference * terrain.propSurfaceTension, 0.0f) -
                                  (new Vector3(0.0f, mass.totalForce.Y, 0.0f) +
                                  new Vector3(0.0f, mass.velocity.Y * mass.mass / Statics_Engine.SystemSettings.dt, 0.0f)));
                }
            }
        }

        /// <summary>
        /// Override draw for portal
        /// </summary>
        public override Draw Draw()
        {
            // Calculate ObjectSpace(Rotation) and WorldSpace(Translation) Transformation Matrix
            draw.matrix = draw.initialTransform * Matrix.CreateScale(mass.scale) *
                          Matrix.CreateFromQuaternion(mass.currentRotation) *
                          Matrix.CreateTranslation(mass.currentPosition);

            return draw;
        }

        /// <summary>
        /// Override and supplement base Billboard drawing specific to this Portal.
        /// </summary>
        /// <param name="objectLibrary">ObjectLibrary that portal belongs to.</param>
        /// <param name="gameObjectBillboards">Dynamic list of billboards to be drawn this frame.</param>
        public override void Draw_Billboards(ObjectLibrary objectLibrary, BillboardList gameObjectBillboards)
        {
            fireIterator++;
            if (fireIterator > 2)
                fireIterator = 0;

            Random random = new Random();

            // Shift Random number between -0.5 and 0.5 to modulate height
            float randOffsetY = (float)random.NextDouble();
            randOffsetY -= 0.5f;
            Vector3 offset = new Vector3(80.0f, 10.0f * randOffsetY + 150.0f, 250.0f * randOffsetY);

            // Random number between 0-3, excluding 4..
            int randTexture = (int)(random.NextDouble() * draw.textureList.Count - .01);

            Billboard billboard = new Billboard(null);
            billboard.Load(mass.currentPosition, offset, 600.0f, 800.0f, draw.textureList[randTexture]);
            gameObjectBillboards.Add(billboard);
        }
    }
}