using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using StrategicCombat.GameDebugTools;
using StrategicCombat.MenuScreens;

namespace StrategicCombat
{
    /// <summary>
    /// This is the main type for this game.
    /// </summary>
    public class GameStrategicCombat : Microsoft.Xna.Framework.Game
    {
        #region Variables

        // A graphics device manager to be able to draw to the screen.
        GraphicsDeviceManager graphics;

        // Handles menu screens (screenManager is a game component)
        ScreenManager screenManager;

        // Preload menu images.
        static readonly string[] preloadAssets = { "MenuAssets/a", "MenuAssets/ammo", "MenuAssets/b", "MenuAssets/blank", "MenuAssets/blueCircle", 
                                                    "MenuAssets/chat_able", "MenuAssets/chat_mute", "MenuAssets/chat_ready", "MenuAssets/chat_talking" 
                                                    , "MenuAssets/dpadd", "MenuAssets/dpadl", "MenuAssets/dpadr", "MenuAssets/dpadu", "MenuAssets/enter"
                                                    , "MenuAssets/escape", "MenuAssets/key_s", "MenuAssets/key_x", "MenuAssets/key_z", "MenuAssets/lthumbd"
                                                    , "MenuAssets/lthumbl", "MenuAssets/lthumbr", "MenuAssets/lthumbu", "MenuAssets/menuBackground" 
                                                    , "MenuAssets/redCircle", "MenuAssets/rthumbl", "MenuAssets/rthumbr", "MenuAssets/rtrig" , 
                                                    "MenuAssets/splashScreen", "MenuAssets/start", "MenuAssets/white-background", "MenuAssets/x" 
                                                    , "MenuAssets/y"};
        
        // Debug system
        //public static DebugSystem debugSystem;

        #endregion

        #region Constructors

        /// <summary>
        /// Create a new game.
        /// </summary>
        public GameStrategicCombat()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            // Debug system.
            //IsFixedTimeStep = false;
            //graphics.SynchronizeWithVerticalRetrace = false;

            // Set the resolution
            graphics.PreferredBackBufferWidth = 1280;
            graphics.PreferredBackBufferHeight = 720;

            // Set the window title
            Window.Title = "Strategic Combat";

            // Create components.
            screenManager = new ScreenManager(this);

            Components.Add(screenManager);
            Components.Add(new MessageDisplayComponent(this));
            Components.Add(new GamerServicesComponent(this));

            // Add the splash screen.
            screenManager.AddScreen(new SplashScreen(), null);

            //// Activate the first screens.
            //screenManager.AddScreen(new BackgroundScreen(), null);
            //screenManager.AddScreen(new MainMenuScreen(), null);

            // Listen for invite notification events.
            NetworkSession.InviteAccepted += (sender, e) => NetworkSessionComponent.InviteAccepted(screenManager, e);

            // To test the trial mode behavior while developing your game,
            // uncomment this line:
            //Guide.SimulateTrialMode = true;
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            //debugSystem = DebugSystem.Initialize(this, "Fonts/gamefont");

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Load assets, images, for network.
            foreach (string asset in preloadAssets)
            {
                Content.Load<object>(asset);
            }

            // Load the sound system.
            Program.audioEngine = new AudioEngine("Content/Audio/StrategicCombatAudio.xgs");
            Program.waveBank = new WaveBank(Program.audioEngine, "Content/Audio/waveBank.xwb");
            Program.soundBank = new SoundBank(Program.audioEngine, "Content/Audio/soundBank.xsb");

            // Start the soundtrack audio
            Program.menuMusic = Program.soundBank.GetCue("menuMusic");
            Program.menuMusic.Play();

            //debugSystem.FpsCounter.Visible = true;
            //debugSystem.TimeRuler.Visible = true;
            //debugSystem.TimeRuler.ShowLog = true;
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // Unload any non SEE GameplayScreen.
            Content.Unload();
        }

        #endregion

        #region Methods

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // tell the TimeRuler that we're starting a new frame. you always want
            // to call this at the start of Update
            //debugSystem.TimeRuler.StartFrame();
            //debugSystem.TimeRuler.BeginMark("Update", Color.Blue);
            
            // Update the audio engine
            Program.audioEngine.Update();

            // Update the game.
            base.Update(gameTime);

            // Stop measuring time for "Update".
            //debugSystem.TimeRuler.EndMark("Update");
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            // Start measuring time for "Draw".
            //debugSystem.TimeRuler.BeginMark("Draw", Color.Yellow);

            graphics.GraphicsDevice.Clear(Color.Black);

            // The real drawing happens inside the screen manager component.
            base.Draw(gameTime);

            // Stop measuring time for "Draw".
            //debugSystem.TimeRuler.EndMark("Draw");
        }

        #endregion

    } // End of class

} // End of namespace
