// Game Name: Flatlands
// Author: John Hurst (sircrowbar@gmail.com) - Crowbar / Johannhat - http://www.badenoughdude.com/
// Started: 4/20/2012
// Last Updated: 4/22/2012
// For Ludum Dare 23!
// Holy crap I forgot to comment the shit out of everything. The good news is that I plan on expanding this game
// further so maybe there will be time for that afterwards! Happy Ludum Day! - JH

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 Microsoft.Xna.Framework.Storage;

using Flatlands.Tiles;
using Flatlands.Input;

namespace Flatlands
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class SpriteManager : Microsoft.Xna.Framework.DrawableGameComponent
    {
        const int TURNS_BEFORE_MOVE = 5;
        const int STANDBY_TILES = 5;

        bool mute = false;
        bool pause = false;
        bool win = false;
        bool midMove = false;

        int currentTurn = 0;
        int currentRound = 1;

        SpriteBatch spriteBatch;
        Backgrounds bg;
        Rectangle windowSize;
        SpriteFont font;

        Player player = new Player();
        
        Grid grid = new Grid();

        List<Tile> standby = new List<Tile>();
        List<Button> buttons = new List<Button>();


        ButtonInput mouseButton = new ButtonInput();
        ButtonInput pauseButton = new ButtonInput(Keys.Space, Buttons.Start);
        ButtonInput muteButton = new ButtonInput(Keys.M, Buttons.Back);
        ButtonInput resetButton = new ButtonInput(Keys.R, Buttons.A);

        SoundEffect music;
        SoundEffectInstance instance;

        WorldInfo winCondition;
        Texture2D blankTexture;

        public SpriteManager(Game game)
            : base(game)
        {
            // TODO: Construct any child components here
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            winCondition.Population = 800;
            winCondition.Nature = 500;
            winCondition.Culture = 100;


            bg = new Backgrounds();
            grid = new Grid();
            buttons.Add(new Button(ButtonType.Build));
            buttons.Add(new Button(ButtonType.Destroy));
            buttons.Add(new Button(ButtonType.Move));
            buttons.Add(new Button(ButtonType.Upgrade));
            base.Initialize();
        }

        protected override void LoadContent()
        {

            spriteBatch = new SpriteBatch(GraphicsDevice);

            windowSize = new Rectangle(0, 0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height);

            blankTexture = Game.Content.Load<Texture2D>(@"blank");
            font = Game.Content.Load<SpriteFont>(@"Fonts\DebugFont");

            bg.setSize = windowSize;

            bg.addBG(new BGLayer(@"Background\spacereal", false, false, new Vector2(1.0f, 1.0f)));
            bg.load(Game.Content);

            music = Game.Content.Load<SoundEffect>(@"Music\flatlands");
             instance = music.CreateInstance();
            instance.IsLooped = true;
            instance.Volume = 0.15f;
            instance.Play();


            grid.load(Game.Content);

            for (int i = 0; i < STANDBY_TILES; i++)
            {
                Tile temp = new Tile();
                temp.load(Game.Content);

                temp.Position = new Vector2((temp.hitBox.Width * i), 380);

                standby.Add(temp);
            }
            grid.SelectRandomCols();

            for(int i = 0; i< buttons.Count; i++)
            {
                buttons[i].load(Game.Content);
            }

            //Setting these manually for now since I'm running short on time.
            buttons[0].Position = new Vector2(550, 200);
            buttons[1].Position = new Vector2(600, 200);
            buttons[2].Position = new Vector2(550, 250);
            buttons[3].Position = new Vector2(600, 250); 
            

        }

        public override void Draw(GameTime gameTime)
        {
            spriteBatch.Begin();

            bg.draw(spriteBatch);

            foreach (Tile tile in standby)
            {
                tile.draw(spriteBatch);
            }

            grid.draw(spriteBatch);

            foreach (Button temp in buttons)
            {
                temp.draw(spriteBatch);
            }

            if (win)
            {
                spriteBatch.DrawString(font, "YOU WIN!\n Press R to start again", new Vector2(525, 0), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0.0f);
            }

            if (midMove)
            {
                spriteBatch.DrawString(font, "Move Set - Click an adjacent tile!", new Vector2(200, 50), Color.Yellow, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0.0f);
            }


            spriteBatch.DrawString(font, "M - Mute", new Vector2(700, 430), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0.0f);
            spriteBatch.DrawString(font, "R - Reset", new Vector2(700, 455), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0.0f);


            spriteBatch.DrawString(font, "Current Round: " + currentRound, new Vector2(5, 175), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0.0f);
            spriteBatch.DrawString(font, "Turn: " + currentTurn, new Vector2(5, 200), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0.0f);
            spriteBatch.DrawString(font, "Turns Left in Round: " + (TURNS_BEFORE_MOVE - currentTurn), new Vector2(5, 225), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0.0f);


            spriteBatch.DrawString(font, "Win Conditions:", new Vector2(25, 25), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0.0f);
            spriteBatch.DrawString(font, "Population: " + winCondition.Population, new Vector2(25, 50), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0.0f);
            spriteBatch.DrawString(font, "Nature: " + winCondition.Nature, new Vector2(25, 75), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0.0f);
            spriteBatch.DrawString(font, "Culture: " + winCondition.Culture, new Vector2(25, 100), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0.0f);



            if (player.Population >= winCondition.Population)
                spriteBatch.DrawString(font, "Population: " + player.Population + " - MET!", new Vector2(525, 75), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0.0f);
            else
                spriteBatch.DrawString(font, "Population: " + player.Population, new Vector2(525, 75), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0.0f);

            if (player.Nature >= winCondition.Nature)
                spriteBatch.DrawString(font, "Nature: " + player.Nature + " - MET!", new Vector2(525, 100), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0.0f);
            else
                spriteBatch.DrawString(font, "Nature: " + player.Nature, new Vector2(525, 100), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0.0f);

            if (player.Culture >= winCondition.Culture)
                spriteBatch.DrawString(font, "Culture: " + player.Culture + " - MET!", new Vector2(525, 125), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0.0f);
            else
                spriteBatch.DrawString(font, "Culture: " + player.Culture, new Vector2(525, 125), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0.0f);
                      
            
            spriteBatch.DrawString(font, "Next:" , new Vector2(0, 355), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0.0f);
            spriteBatch.DrawString(font, "Standby Tiles", new Vector2(510, 455), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0.0f);

            spriteBatch.DrawString(font, "Mode: " + player.mode.ToString(), new Vector2(550, 300), Color.Yellow, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0.0f);
            spriteBatch.DrawString(font, "Click any button \n to set mode.", new Vector2(550, 350), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0.0f);

            spriteBatch.End();

            if (pause)
                FadeBackBufferToBlack(100);

            
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            // TODO: Add your update code here
            
            MouseState mouse = Mouse.GetState();
            KeyboardState keyState = Keyboard.GetState();
            GamePadState padState = GamePad.GetState(PlayerIndex.One);

            if (pauseButton.press(keyState, padState))
            {
                pause = (pause) ? false : true;
                if (pause)
                    instance.Pause();
                else
                    instance.Resume();
                
            }

            if (pause)
            {
                return;
            }

            if (muteButton.press(keyState, padState))
            {
                mute = (mute) ? false : true;
                if (mute)
                    instance.Stop();
                else
                    instance.Play();
  
            }

            if (resetButton.press(keyState, padState))
            {
                reset();
            }

            if (win)
            {
                return;
            }

            //player.update();
            bg.update(Vector2.Zero);

            if (mouseButton.leftClick(mouse))
            {
                Rectangle mouseRect = new Rectangle(mouse.X, mouse.Y, 1, 1);
                foreach (Button temp in buttons)
                {
                    if (mouseRect.Intersects(temp.hitBox))
                    {
                        player.changeMode(temp.type);
                        midMove = false;
                    }
                }

                if (mouseRect.Intersects(grid.hitBox))
                {

                    bool turn = false;

                    switch (player.mode)
                    {
                        case ButtonType.Build:
                            turn = grid.addTile(standby[0], new Vector2(mouse.X, mouse.Y), Game.Content);
                    
                            if (turn)
                            {
                                currentTurn++;
                                standby.RemoveAt(0);
                                Tile newTile = new Tile();
                                newTile.load(Game.Content);
                                newTile.Position = new Vector2((newTile.hitBox.Width * standby.Count), 380);
                                standby.Add(newTile);
                                updateStandbyPos();
                            } 


                            break;
                        case ButtonType.Destroy:
                            turn = grid.destroyTile(new Vector2(mouse.X, mouse.Y));

                            if (turn)
                            {
                                currentTurn++;
                            }
                            break;
                                        
                        case ButtonType.Move:
                            if (!midMove)
                            {
                                bool setMove = grid.selectTileToMove(new Vector2(mouse.X, mouse.Y));

                                if (setMove)
                                    midMove = true;
                                
                            }
                            else
                            {
                                turn = grid.moveTile(new Vector2(mouse.X, mouse.Y), Game.Content);

                                if (turn)
                                {
                                    currentTurn++;
                                    midMove = false;
                                }
                            }

                            break;

                        case ButtonType.Upgrade:
                            turn = grid.upgradeTile(new Vector2(mouse.X, mouse.Y), Game.Content);

                            if (turn)
                            {
                                currentTurn++;
                            }
                            break;
                    }

                }

                if (currentTurn == TURNS_BEFORE_MOVE)
                {
                    grid.MoveRandomCols();
                    currentTurn = 0;
                    currentRound++;
                }

                
            }
            
            grid.update(gameTime);

            WorldInfo info = grid.getInfo();

            player.Population = info.Population;
            player.Nature = info.Nature;
            player.Culture = info.Culture;

            if (player.Population >= winCondition.Population &&
                player.Nature >= winCondition.Nature &&
                player.Culture >= winCondition.Culture)
            {
                win = true;
                instance.Stop();
            }

            base.Update(gameTime);
        }


        public void updateStandbyPos()
        {
            for (int i = 0; i < STANDBY_TILES; i++)
            {
                standby[i].Position = new Vector2((standby[i].hitBox.Width * i), 380);
            }
        }

        public void reset()
        {
            player.Population = 0;
            player.Nature = 0;
            player.Culture = 0;
            instance.Play();
            grid.reset();
            standby.Clear();
            for (int i = 0; i < STANDBY_TILES; i++)
            {
                Tile temp = new Tile();
                temp.load(Game.Content);

                temp.Position = new Vector2((temp.hitBox.Width * i), 380);

                standby.Add(temp);
            }
            currentTurn = 0;
            currentRound = 1;

            grid.SelectRandomCols();

        }
        public void FadeBackBufferToBlack(int alpha)
        {
            Viewport viewport = GraphicsDevice.Viewport;

            spriteBatch.Begin();

            spriteBatch.Draw(blankTexture,
                             new Rectangle(0, 0, viewport.Width, viewport.Height),
                             new Color(0, 0, 0, (byte)alpha));
            string pauseString = "P    A    U    S    E    !";
            spriteBatch.DrawString(font, pauseString, new Vector2(320, 240), Color.Crimson, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0.0f);

            spriteBatch.End();
        }


    }

}