#region Using Statements
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Input;
#endregion

namespace GhostArena3D
{
   public enum LobbyState
   {
      SEARCH_FOR_GAMES,
      IN_LOBBY
   }

   class GameLobbyScreen : GameScreen
   {
      int gameDifficulty;
      GameType gameType;
      LobbyState lobbyState;

      NetworkSession session;
      AvailableNetworkSessionCollection availableSessions;

      int selectedSessionIndex;
      bool returnFromGame;

      #region Initialize

      public GameLobbyScreen(int difficulty, GameType type, bool returningFromGame)
      {
         gameDifficulty = difficulty;
         gameType = type;
         selectedSessionIndex = 0;

         TransitionOnTime = TimeSpan.FromSeconds(1.5);
         TransitionOffTime = TimeSpan.FromSeconds(0.5);
         
         session = null;
         availableSessions = null;
         
         returnFromGame = returningFromGame;
      }


      public override void LoadContent()
      {
         base.LoadContent();
         
         if(gameType == GameType.MULTI_PLAYER_HOST)
         {
            if(returnFromGame == false)
               ((GhostArena3D)ScreenManager.Game).CreateSession();

            session = ((GhostArena3D)ScreenManager.Game).NetworkSession;
            lobbyState = LobbyState.IN_LOBBY;
         }
         else if(gameType == GameType.MULTI_PLAYER_CLIENT)
         {
            if(returnFromGame == true)
            {
               session = ((GhostArena3D)ScreenManager.Game).NetworkSession;
               lobbyState = LobbyState.IN_LOBBY;
            }
            else
            {
               ((GhostArena3D)ScreenManager.Game).SearchForGames();
               availableSessions = ((GhostArena3D)ScreenManager.Game).AvailableSessions;
               lobbyState = LobbyState.SEARCH_FOR_GAMES;
            }
         }
      }


      public override void UnloadContent()
      {
         if(session != null)
         {
            if(session.SessionState != NetworkSessionState.Playing)
            {
               ((GhostArena3D)ScreenManager.Game).DestroyNetworkSession();
               ((GhostArena3D)ScreenManager.Game).DestroyAvailableSessions();
            }
         }

         base.UnloadContent();
      }
      
      #endregion
      
      #region Input
      
      public bool IsButtonXPressed(InputState input)
      {
         ButtonState state = input.CurrentGamePadStates[0].Buttons.X;
         ButtonState oldState = input.LastGamePadStates[0].Buttons.X;

         if(state == ButtonState.Pressed && oldState == ButtonState.Released)
            return true;

         return false;
      }
      
      
      public bool IsButtonBPressed(InputState input)
      {
         ButtonState state = input.CurrentGamePadStates[0].Buttons.B;
         ButtonState oldState = input.LastGamePadStates[0].Buttons.B;

         if(state == ButtonState.Pressed && oldState == ButtonState.Released)
            return true;

         return false;
      }
      
      
      public bool IsButtonAPressed(InputState input)
      {
         ButtonState state = input.CurrentGamePadStates[0].Buttons.A;
         ButtonState oldState = input.LastGamePadStates[0].Buttons.A;

         if(state == ButtonState.Pressed && oldState == ButtonState.Released)
            return true;

         return false;
      }
      
      
      public bool IsButtonArrowUpPressed(InputState input)
      {
         ButtonState state = input.CurrentGamePadStates[0].DPad.Up;
         ButtonState oldState = input.LastGamePadStates[0].DPad.Up;

         if(state == ButtonState.Pressed && oldState == ButtonState.Released)
            return true;

         return false;
      }
      
      
      public bool IsButtonArrowDownPressed(InputState input)
      {
         ButtonState state = input.CurrentGamePadStates[0].DPad.Down;
         ButtonState oldState = input.LastGamePadStates[0].DPad.Down;

         if(state == ButtonState.Pressed && oldState == ButtonState.Released)
            return true;

         return false;
      }


      public override void HandleInput(InputState input)
      {
         if(SignedInGamer.SignedInGamers.Count == 0)
            return;

         if(IsButtonBPressed(input))
            this.ExitScreen();

         if(lobbyState == LobbyState.IN_LOBBY)
            HandleLobbyInput(input);
         else
            HandleGameSearchInput(input);
         
         base.HandleInput(input);
      }
      
      
      private void HandleLobbyInput(InputState input)
      {
         if(session == null)
            return;

         // Ready-Up.
         if(IsButtonXPressed(input))
         {
            foreach(LocalNetworkGamer gamer in session.LocalGamers)
               gamer.IsReady = !gamer.IsReady;
         }
      }
      
      
      private void HandleGameSearchInput(InputState input)
      {
         if(availableSessions == null)
            return;

         if(IsButtonAPressed(input))
         {
            if(availableSessions.Count > 0)
            {
               ((GhostArena3D)ScreenManager.Game).JoinGame(selectedSessionIndex);
               session = ((GhostArena3D)ScreenManager.Game).NetworkSession;
               lobbyState = LobbyState.IN_LOBBY;
            }
         }
         else if(IsButtonArrowUpPressed(input))
         {
            if(selectedSessionIndex > 0)
               selectedSessionIndex--;
         }
         else if(IsButtonArrowDownPressed(input))
         {
            if(selectedSessionIndex < availableSessions.Count - 1)
               selectedSessionIndex++;
         }
      }
      
      #endregion

      #region Update

      public override void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen)
      {
         // Start game if all is ready.
         if(session != null)
         {
            if(session.IsEveryoneReady == true && session.SessionState == NetworkSessionState.Playing)
            {
               LoadingScreen.Load(ScreenManager, true, new
                                  GameplayScreen(gameDifficulty, gameType));
            }
            
            // Start game if all is ready.
            if(session.IsHost == true)
            {
               if(session.IsEveryoneReady == true && session.AllGamers.Count > 1)
               {
                  if(session.SessionState != NetworkSessionState.Playing)
                     session.StartGame();
               }
            }
         }

         base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
      }
      
      #endregion

      #region Drawing

      public override void Draw(GameTime gameTime)
      {
         ScreenManager.GraphicsDevice.Clear(ClearOptions.Target, Color.Black, 0, 0);

         if(lobbyState == LobbyState.IN_LOBBY)
            DrawLobby();
         else
            DrawGameSearch();

         if(TransitionPosition > 0)
            ScreenManager.FadeBackBufferToBlack(255 - TransitionAlpha);
      }
      
      
      private void DrawLobby()
      {
         if(session == null)
            return;

         Color textColor = new Color(255, 255, 255, TransitionAlpha);
         Color borderColor = new Color(100, 100, 100, TransitionAlpha);
         SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
         SpriteFont font = ScreenManager.Font;

         float y = 100;

         spriteBatch.Begin();

         spriteBatch.DrawString(font, "Lobby (X = Ready, B = Leave)",
                                new Vector2(101, y + 1), borderColor);

         spriteBatch.DrawString(font, "Lobby (X = Ready, B = Leave)",
                                new Vector2(101, y), textColor);

         y += font.LineSpacing * 2;

         foreach(NetworkGamer gamer in session.AllGamers)
         {
            Player player = gamer.Tag as Player;
            string text = gamer.Gamertag;
            
            if(gamer.IsReady)
               text += " - Ready To Play!";

            if(player.GamerPic != null)
               spriteBatch.Draw(player.GamerPic, new Vector2(100, y), Color.White);

            spriteBatch.DrawString(font, text, new Vector2(170, y), textColor);

            y += font.LineSpacing + 64;
         }

         spriteBatch.End();
      }
      
      
      private void DrawGameSearch()
      {
         string errorDisplay = null;
         
         if(availableSessions == null)
         {
            errorDisplay = "You must connect to a network!";
         }

         if(availableSessions != null)
         {
            if(availableSessions.Count <= 0)
               errorDisplay = "No Games Found!";
         }

         Color textColor = new Color(255, 255, 255, TransitionAlpha);
         Color borderColor = new Color(100, 100, 100, TransitionAlpha);
         SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
         SpriteFont font = ScreenManager.Font;

         float y = 100;
         
         spriteBatch.Begin();

         if(errorDisplay != null)
         {
            spriteBatch.DrawString(font, "No Games Found!",
                                   new Vector2(101, y + 1), borderColor);

            spriteBatch.DrawString(font, "No Games Found!",
                                   new Vector2(100, y), textColor);
         }
         else
         {
            spriteBatch.DrawString(font, "Game List (A = Join, B = Back)",
                                   new Vector2(101, y + 1), borderColor);

            spriteBatch.DrawString(font, "Game List (A = Join, B = Back)",
                                   new Vector2(100, y), textColor);

            y += font.LineSpacing * 2;

            for(int i = 0; i < availableSessions.Count; i++)
            {
               if(i == selectedSessionIndex)
                  textColor = Color.Yellow;
               else
                  textColor = Color.White;

               spriteBatch.DrawString(font, availableSessions[i].HostGamertag,
                                      new Vector2(100, y), textColor);

               y += font.LineSpacing;
            }
         }

         spriteBatch.End();
      }
      
      #endregion
   }
}
