#region Using directives

using System;
using System.Drawing;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using D3D = Microsoft.DirectX.Direct3D;
using DI = Microsoft.DirectX.DirectInput;

#endregion

namespace PunkMan.Game
{
    /// <summary>
    /// Basic menu class
    /// </summary>
    public class Menu
    {
        private D3D.Font font = null;
        private D3D.Device dev;
        private DI.Device devInp;
        private string[] items = null;
        private int active = 0;
        private Game owner = null;
        private VertexBuffer vb = null;
        private Texture tex = null;

        /// <summary>
        /// OOoo mighty constructor
        /// </summary>
        /// <param name="owner">game owner</param>
        /// <param name="dev">graphics device</param>
        /// <param name="devi">input device</param>
        public Menu(Game owner, D3D.Device dev, DI.Device devi)
        {
            this.owner = owner;
            devInp = devi;
            this.dev = dev;
            font = new D3D.Font(dev, new System.Drawing.Font("Arial", 32));
            vb = new VertexBuffer(typeof(CustomVertex.PositionNormalTextured), 4, dev,
                Usage.WriteOnly, CustomVertex.PositionNormalTextured.Format, Pool.Default);
            vb.Created += new EventHandler(this.OnCreateVB);
            OnCreateVB(vb, null);
            tex = TextureLoader.FromFile(dev, Game.GetDataFilePath(@"artwork\menu.jpg"));

        }

        private void OnCreateVB(object sender, EventArgs args)
        {
            VertexBuffer vb = (VertexBuffer)sender;
            CustomVertex.PositionNormalTextured[] vert = (CustomVertex.PositionNormalTextured[])vb.Lock(0, 0);
            vert[0].Position = (new Vector3(0, 0, 1));
            vert[0].Tu = 0;
            vert[0].Tv = 1;
            vert[1].Position = (new Vector3(1, 0, 1));
            vert[1].Tu = 1;
            vert[1].Tv = 1;
            vert[2].Position = (new Vector3(0, 1, 1));
            vert[2].Tu = 0;
            vert[2].Tv = 0;
            vert[3].Position = (new Vector3(1, 1, 1));
            vert[3].Tu = 1;
            vert[3].Tv = 0;
            for (int i = 0; i < 4; i++) vert[i].Normal = (new Vector3(0, 0, -1));
            vb.Unlock();

        }


        private void Render()
        {
            if (dev == null) return;
            if (items == null) return;
            dev.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0);

            dev.BeginScene();
            dev.Transform.World = Matrix.Identity;

            dev.RenderState.Lighting = false;
            dev.RenderState.ZBufferEnable = false;

            dev.Transform.World = Matrix.Identity;
            dev.Transform.View = Matrix.Identity;
            dev.Transform.Projection = Matrix.OrthoLH(owner.Width, owner.Height, 0, 1);

            /*Matrix trans = Matrix.Scaling(owner.Width, owner.Height, 1);
            trans.Multiply(Matrix.Translation(-owner.Width / 2, -owner.Height / 2, 0));
            dev.Transform.World = trans;

            dev.SetTexture(0, tex);

            dev.SetStreamSource(0, vb, 0);
            dev.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);*/

            for (int i = 0; i < items.Length; i++)
            {
                font.DrawText(null, items[i], new Rectangle(10, (84 * owner.Height / 600) + i * 80, 800, 100), 
                    DrawTextFormat.Left,
                    (i == active) ? Color.Red : Color.LightGreen);
            }


            dev.EndScene();
            dev.Present();

        }

        private bool end;
        private bool esc;
        /// <summary>
        /// Execute menu
        /// </summary>
        /// <param name="items">menu items</param>
        /// <param name="canEsc">can be interupted by pressing escape?</param>
        /// <returns></returns>
        public int Execute(string[] items, bool canEsc)
        {
            end = false;
            esc = false;
            if (items == null) return -1;
            this.items = items;
            while (!end)
            {
                float time = Game.Time();
                while (Game.Time() < time + 0.075) ;
                HandleEvents(canEsc);
                Render();
            }
            return (esc && canEsc) ? -1 : active;
        }

        private void HandleEvents(bool canEsc)
        {
            DI.KeyboardState state = devInp.GetCurrentKeyboardState();
            if (state[DI.Key.UpArrow]) active--;
            else if (state[DI.Key.DownArrow]) active++;
            else if (state[DI.Key.Return]) end = true;
            else if (state[DI.Key.Escape] && canEsc)
            {
                end = true;
                esc = true;
            }
            if (active < 0) active = items.Length - 1;
            if (active >= items.Length) active = 0;
        }
    }
}
