using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Globalization;
using System.Text;
using System.Collections.Generic;
#if XBOX
using System.Reflection;
#endif

namespace ECOT.Engine
{
    /// <summary>
    /// 
    /// </summary>
    public static class Utilities
    {
        #region Methods

        /// <summary>
        /// 
        /// </summary>
        /// <param name="type"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        public static Vector2 GetHotSpot(HotSpotType type, Size size)
        {
            Vector2 vSize = new Vector2((float)size.Width, (float)size.Height);

            switch (type)
            {
                case HotSpotType.TopLeft:
                    return Vector2.Zero;

                case HotSpotType.TopRight:
                    return new Vector2(vSize.X, 0.0f);

                case HotSpotType.BottomLeft:
                    return new Vector2(0.0f, vSize.Y);

                case HotSpotType.BottomRight:
                    return vSize;

                case HotSpotType.Center:
                    return (vSize * 0.5f);

                case HotSpotType.LeftCenter:
                    return new Vector2(0.0f, vSize.Y * 0.5f);

                case HotSpotType.RightCenter:
                    return new Vector2(vSize.X, vSize.Y * 0.5f);

                case HotSpotType.TopCenter:
                    return new Vector2(vSize.X * 0.5f, 0.0f);

                case HotSpotType.BottomCenter:
                    return new Vector2(vSize.X * 0.5f, vSize.Y);

                // Custom (un peu idiot, mais il faut toujours penser que l'utilisateur est un autiste :-D
                default:
                    return Vector2.Zero;
            }
        }

        public static float GetAngleFrom2DVectors(Vector2 OriginLoc, Vector2 TargetLoc, bool bRadian)
        {
            double Angle;
            float xDist = OriginLoc.X - TargetLoc.X;
            float yDist = OriginLoc.Y - TargetLoc.Y;
            double norm = System.Math.Abs(xDist) + System.Math.Abs(yDist);

            if ((xDist >= 0) & (yDist >= 0))
            {
                //Lower Right Quadran
                Angle = 90 * (yDist / norm) + 270;
            }
            else if ((xDist <= 0) && (yDist >= 0))
            {
                //Lower Left Quadran
                Angle = -90 * (yDist / norm) + 90;
            }
            else if (((xDist) <= 0) && ((yDist) <= 0))
            {
                //Upper Left Quadran
                Angle = 90 * (xDist / norm) + 180;
            }
            else
            {
                //Upper Right Quadran
                Angle = 90 * (xDist / norm) + 180;
            }

            if (bRadian)
                Angle = MathHelper.ToRadians(System.Convert.ToSingle(Angle));

            return Convert.ToSingle(Angle);
        }

        public static Color Lerp(Color c1, Color c2, float f)
        {
            byte a = (byte)(c1.A + (c2.A - c1.A) * f);
            byte r = (byte)(c1.R + (c2.R - c1.R) * f);
            byte g = (byte)(c1.G + (c2.G - c1.G) * f);
            byte b = (byte)(c1.B + (c2.B - c1.B) * f);
            return new Color(r, g, b, a);
        }

        #endregion

        public static Vector2 GetAbsoluteCoords(float x, float y)
        {
            return new Vector2(x / 1280.0f * Kernel.Instance.Width, y / 720.0f * Kernel.Instance.Height);
        }

        public static string WrapText(string text, int width, SpriteFont font)
        {
            StringBuilder builder = new StringBuilder();
            float spaceWidth = font.MeasureString(" ").X;
            float lineWidth = 0.0f;

            string[] lines = text.Split('\n');
            foreach (string line in lines)
            {
                string[] words = line.Split(' ');
                foreach (string word in words)
                {
                    float wordWidth = font.MeasureString(word).X;
                    if (lineWidth + wordWidth < width)
                    {
                        builder.Append(word + " ");
                        lineWidth += wordWidth + spaceWidth;
                    }
                    else
                    {
                        builder.Append("\n" + word + " ");
                        lineWidth = wordWidth + spaceWidth;
                    }
                }

                builder.Append("\n");
                lineWidth = 0;
            }

            return builder.ToString();
        }

        public static string[] BreakLines(string text, int width, SpriteFont font)
        {
            return WrapText(text, width, font).Split('\n');
        }

        public static float Random(float min, float max)
        {
            int iMin = (int)(min * 1000.0f);
            int iMax = (int)(max * 1000.0f);
            float rnd = m_Random.Next(iMin, iMax);

            return (rnd / 1000.0f);
        }

        public static int RandomInt(int min, int max)
        {
            return m_Random.Next(min, max);
        }

        public static string RandomName()
        {
            return Guid.NewGuid().ToString();
        }

#if XBOX
        public static Enum ParseEnum(System.Type enumType, string val)
        {
            FieldInfo fInfo = enumType.GetField(val, BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static);
            if (fInfo == null)
            {
                throw new ArgumentException("Enum member not exist: " + val);
            }
            return (Enum)fInfo.GetValue(null);
        }
#endif

        private static Random m_Random = new Random();
    }

    /// <summary>
    /// 
    /// </summary>
    public class Size
    {
        #region Initialization

        /// <summary>
        /// 
        /// </summary>
        /// <param name="size"></param>
        public Size(int size)
        {
            this.width = this.height = size;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        public Size(int width, int height)
        {
            this.width = width;
            this.height = height;
        }

        #endregion

        #region Properties

        /// <summary>
        /// 
        /// </summary>
        public int Width
        {
            get { return this.width; }
        }

        /// <summary>
        /// 
        /// </summary>
        public int Height
        {
            get { return this.height; }
        }

        #endregion

        #region Fields

        /// <summary>
        /// 
        /// </summary>
        private int width, height;

        #endregion
    }
}
