using System.Globalization;
using System.Reflection;
using ECOT.Engine.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;

#if !XBOX
using Microsoft.Win32;
using Microsoft.Xna.Framework.Content;
using System;
#endif


namespace ECOT.Engine
{
    public delegate void LocaleChangeHandler(CultureInfo locale);

    /// <summary>
    /// 
    /// </summary>
    public class Kernel
    {
        private Viewport defaultViewport;
        private bool useTitleSafe = false;

        public event LocaleChangeHandler OnLocaleChange;

        #region Initialization
        
        public Kernel(Game game, Size windowSize, bool fullscreen)
        {
            // Creates and configures the graphic device
            this.graphicsManager = new GraphicsDeviceManager(game);
            this.graphicsManager.PreferredBackBufferWidth = windowSize.Width;
            this.graphicsManager.PreferredBackBufferHeight = windowSize.Height;
#if DEBUG
            this.graphicsManager.IsFullScreen = false;
#else
            this.graphicsManager.IsFullScreen = fullscreen;
#endif
            this.graphicsManager.PreferMultiSampling = true;

            // Keeps a game reference
            this.game = game;
            // Keeps the engine instance
            Kernel.instance = this;
        }

        public void Initialize(string bootstrapPath, string textResources, Assembly asm)
        {
            this.Locale = CultureInfo.CurrentUICulture;
            this.DefaultLocale = CultureInfo.CurrentUICulture;

            // For old CRT 4.3 TVs, we crop the drawing region to a safe zone
            if (this.GraphicsDevice.DisplayMode.AspectRatio == 4.0f / 3.0f)
            {
                Viewport viewport = new Viewport();
                viewport.X = this.GraphicsDevice.Viewport.TitleSafeArea.X;
                viewport.Y = this.GraphicsDevice.Viewport.TitleSafeArea.Y;
                viewport.Width = this.GraphicsDevice.Viewport.TitleSafeArea.Width;
                viewport.Height = this.GraphicsDevice.Viewport.TitleSafeArea.Height;

                this.defaultViewport = this.GraphicsDevice.Viewport;
                this.useTitleSafe = true;
            }

            this.graphicsManager.GraphicsDevice.Clear(Color.Black);

            // Current directory
#if !XBOX
            RegistryKey ecoKey = Registry.LocalMachine.OpenSubKey(@"Software\ECOThink");
            this.currentDirectory = (ecoKey != null ? (string)ecoKey.GetValue("InstallPath") + @"\" ?? @".\" : @".\");
#else
            this.currentDirectory = @".\";
#endif
            
            // Creates sprite batch
            this.spriteBatch = new SpriteBatch(this.graphicsManager.GraphicsDevice);

            // Creates the text manager
            this.textMgr = new TextManager(textResources, asm);

            // Crée le content Manager
            this.contentManager = new ContentManager(game.Services, Environment.CurrentDirectory);
 
            // Creates the media manager
            this.mediaManager = new MediaManager(this.contentManager);

            // Creates camera
            this.camera = new Camera();

            // Crée le curseur
            this.cursor = new Cursor();

            // Crée la machine à état
            this.stateManager = new StateManager(game);
            game.Components.Add(stateManager);

        }

        public void Clear()
        {
            if (this.useTitleSafe)
            {
                Viewport viewport = this.GraphicsDevice.Viewport;

                this.GraphicsDevice.Viewport = this.defaultViewport;
                this.GraphicsDevice.Clear(Color.Black);

                this.GraphicsDevice.Viewport = viewport;
            }
            else
                this.GraphicsDevice.Clear(Color.Black);
        }


        #endregion

        #region Properties

        public string CurrentDirectory
        {
            get { return this.currentDirectory; }
        }

        public StateManager StateManager
        {
            get { return this.stateManager; }
        }

        public Game Game
        {
            get { return this.game; }
        }

        public GraphicsDeviceManager GraphicsManager
        {
            get { return this.graphicsManager; }
        }

        public GraphicsDevice GraphicsDevice
        {
            get { return this.graphicsManager.GraphicsDevice; }
        }

        public AudioEngine Audio
        {
            get { return this.audioEngine; }
            set { this.audioEngine = value; }
        }

        public int Width
        {
            get { return this.graphicsManager.GraphicsDevice.Viewport.Width; }           
        }

        public int Height
        {
            get { return this.graphicsManager.GraphicsDevice.Viewport.Height; }           
        }

        public SpriteBatch SpriteBatch
        {
            get { return this.spriteBatch; }
            set { this.spriteBatch = value; }
        }

        public MediaManager Medias
        {
            get { return this.mediaManager; }
        }

        public GameTime Time
        {
            get { return this.gameTime; }
            set { this.gameTime = value; }
        }

        public Camera Camera
        {
            get { return this.camera; }
            set { this.camera = value; }
        }

        public Cursor Cursor
        {
            get { return this.cursor; }
            set { this.cursor = value; }
        }

        public Vector2 Origin
        {
            get { return this.camera.Position; }
        }

        public float Zoom
        {
            get { return this.camera.Zoom; }
            set { this.camera.Zoom = value; }
        }

        public string DataPath
        {
            get { return this.dataPath; }
            set { this.dataPath = value; }
        }

        public string FontPath
        {
            get { return this.fontPath; }
            set { this.fontPath = value; }
        }

        public string UiPath
        {
            get { return this.uiPath; }
            set { this.uiPath = value; }
        }

        public InputState Input
        {
            get { return this.inputState; }
        }

        public float TotalElapsedSeconds
        {
            get { return this.totalElapsedSeconds; }
            set { this.totalElapsedSeconds = value; }
        }

        public ThreadPool ThreadPool
        {
            get { return this.threadPool; }
        }

        public CultureInfo Locale
        {
            get { return this.locale; }
            set
            {
                switch (value.TwoLetterISOLanguageName)
                {
                    default:
                    case "en":
                        value = new CultureInfo("en-US");
                        this.localeIndex = 0;
                        break;

                    case "fr":
                        this.localeIndex = 1;
                        break;

                    case "es":
                        this.localeIndex = 2;
                        break;

                    case "it":
                        this.localeIndex = 3;
                        break;
                }

                this.locale = value;


                if (this.OnLocaleChange != null)
                    this.OnLocaleChange(this.locale);
            }
        }

        public TextManager Text
        {
            get { return this.textMgr; }
        }

        public int LocaleIndex
        {
            get { return this.localeIndex; }
        }

        public CultureInfo DefaultLocale 
        {
            get { return this.defaultLocale; }
            set { this.defaultLocale = value; }
        }

#if XBOX
        public XboxControllerButtons XboxControllerButtons
        {
            get { return this.xboxControllerButtons; }
        }
#endif

        public static Kernel Instance
        {
            get { return instance; }
        }

        #endregion

        #region Membres

        private string currentDirectory;

        /// <summary>
        /// 
        /// </summary>
        private Game game;

        /// <summary>
        /// 
        /// </summary>
        private GraphicsDeviceManager graphicsManager;

        /// <summary>
        /// 
        /// </summary>
        private AudioEngine audioEngine;

        /// <summary>
        /// 
        /// </summary>
        private SpriteBatch spriteBatch;

        /// <summary>
        /// 
        /// </summary>
        private TextManager textMgr;

        /// <summary>
        /// 
        /// </summary>
        private MediaManager mediaManager;

        /// <summary>
        /// 
        /// </summary>
        private StateManager stateManager;
        /// <summary>
        /// 
        /// </summary>
        private GameTime gameTime;

        /// <summary>
        /// 
        /// </summary>
        private ContentManager contentManager;
        /// <summary>
        /// 
        /// </summary>
        private Camera camera;

        /// <summary>
        /// 
        /// </summary>
        private Cursor cursor;

        /// <summary>
        /// 
        /// </summary>
        private InputState inputState = new InputState();


        /// <summary>
        /// 
        /// </summary>
        private float totalElapsedSeconds = 0.0f;

        private ThreadPool threadPool = new ThreadPool();

        /// <summary>
        /// 
        /// </summary>
        private static Kernel instance = null;

        private string dataPath = @"Data\";

        private string fontPath = @"Fonts\";

        private string uiPath = @"Textures\Interface\";

        private CultureInfo locale;
        private CultureInfo defaultLocale;

        private int localeIndex;

#if XBOX

        private XboxControllerButtons xboxControllerButtons;

#endif

        #endregion

        public void KillAllThreads()
        {
            this.threadPool.Kill();
            //this.mediaManager.Kill();
        }
    }
}
