#region File Description
//-----------------------------------------------------------------------------
// MenuScreen.cs
//
// XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
#endregion

namespace GhostArena3
{
    /// <summary>
    /// Base class for screens that contain a menu of options. The user can
    /// move up and down to select an entry, or cancel to back out of the screen.
    /// </summary>
    abstract class MenuScreen : GameScreen
    {
        #region Fields

        protected List<string> _menuEntries = new List<string>();
        int _selectedEntry = 0;

        #endregion

        #region Properties


        /// <summary>
        /// Gets the list of menu entry strings, so derived classes can add
        /// or change the menu contents.
        /// </summary>
        protected IList<string> MenuEntries
        {
            get { return _menuEntries; }
        }


        #endregion

        #region Initialization


        /// <summary>
        /// Constructor.
        /// </summary>
        public MenuScreen()
        {
            TransitionOnTime = TimeSpan.FromSeconds(0.5);
            TransitionOffTime = TimeSpan.FromSeconds(0.5);
        }

        public override void Initialize()
        {
            base.Initialize();
        }

        #endregion

        #region Handle Input


        /// <summary>
        /// Responds to user input, changing the selected entry and accepting
        /// or cancelling the menu.
        /// </summary>
        //JEP: updated
        public override void HandleInput(InputState input, GameTime gameTime)
        {
            // Move to the previous menu entry?
            if (input.MenuUp)
            {
                _selectedEntry--;

                if (_selectedEntry < 0)
                    _selectedEntry = _menuEntries.Count - 1;
            }

            // Move to the next menu entry?
            if (input.MenuDown)
            {
                _selectedEntry++;

                if (_selectedEntry >= _menuEntries.Count)
                    _selectedEntry = 0;
            }

            // Accept or cancel the menu?
            if (input.MenuSelect)
            {
                OnSelectEntry(_selectedEntry);
                ((Game1)ScreenManager.Game).soundbank.PlayCue("menu");

            }
            else if (input.MenuCancel)
            {
                OnCancel();
            }

            //JEP: updated
            if (input.IsNewKeyPress(Keys.Left))
                OnNewArrowDown(Keys.Left, _selectedEntry);
            else if (input.IsKeyDown(Keys.Left))
                OnArrowDown(Keys.Left, _selectedEntry, gameTime);
                

            if (input.IsNewKeyUp(Keys.Left))
                OnArrowUp(Keys.Left, _selectedEntry);

            if (input.IsNewKeyPress(Keys.Right))
                OnNewArrowDown(Keys.Right, _selectedEntry);
            else if (input.IsKeyDown(Keys.Right))
                OnArrowDown(Keys.Right,_selectedEntry, gameTime);

            if (input.IsNewKeyUp(Keys.Right))
                OnArrowUp(Keys.Right, _selectedEntry);

        }


        /// <summary>
        /// Notifies derived classes that a menu entry has been chosen.
        /// </summary>
        protected abstract void OnSelectEntry(int entryIndex);

        //JEP: updated
        protected virtual void OnNewArrowDown(Keys arrow, int entryIndex)
        {
        }

        protected virtual void OnArrowDown(Keys arrow, int entryIndex, GameTime gameTime)
        {
        }

        protected virtual void OnArrowUp(Keys arrow, int entryIndex)
        {
        }

        /// <summary>
        /// Notifies derived classes that the menu has been cancelled.
        /// </summary>
        protected abstract void OnCancel();


        #endregion

        #region Draw


        /// <summary>
        /// Draws the menu.
        /// </summary>
        public override void Draw(GameTime gameTime)
        {
            Vector2 position = new Vector2(100, 150);

            // Make the menu slide into place during transitions, using a
            // power curve to make things look more interesting (this makes
            // the movement slow down as it nears the end).
            float transitionOffset = (float)Math.Pow(TransitionPosition, 2);

            if (ScreenState == ScreenState.TransitionOn)
                position.X -= transitionOffset * 256;
            else
                position.X += transitionOffset * 512;

            // Draw each menu entry in turn.
            ScreenManager.SpriteBatch.Begin();

            for (int i = 0; i < _menuEntries.Count; i++)
            {
                Color color;
                float scale;

                if (IsActive && (i == _selectedEntry))
                {
                    // The selected entry is yellow, and has an animating size.
                    double time = gameTime.TotalGameTime.TotalSeconds;

                    float pulsate = (float)Math.Sin(time * 6) + 1;
                    
                    color = Color.Yellow;
                    scale = 1 + pulsate * 0.05f;
                }
                else
                {
                    // Other entries are white.
                    color = Color.White;
                    scale = 1;
                }

                // Modify the alpha to fade text out during transitions.
                color = new Color(color.R, color.G, color.B, TransitionAlpha);

                // Draw text, centered on the middle of each line.
                Vector2 origin = new Vector2(0, ScreenManager.Font.LineSpacing / 2);

                ScreenManager.SpriteBatch.DrawString(ScreenManager.Font, _menuEntries[i],
                                                     position, color, 0, origin, scale,
                                                     SpriteEffects.None, 0);

                position.Y += ScreenManager.Font.LineSpacing;
            }

            ScreenManager.SpriteBatch.End();
        }


        #endregion
    }
}
