using ActionGame.GameArtifacts.Models.Characters;
using ActionGame.GameArtifacts.Models.Items;
using ActionGame.GameResources.Models;
using ActionGame.UserInterface.Control;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;


namespace ActionGame.UserInterface.Screen
{
    public class InventoryScreen : Screen
    {
        public override ControlCollection Controls { get; }

        private PlayerHud playerHud;
        private Label selectedItemDescriptionLabel;
        private Label slot1ItemDescriptionLabel;
        private Label slot2ItemDescriptionLabel;
        private Label playerStatsLabel;
        private MiniMapViewer miniMapViewer;
        private List<InventoryItem> inventoryItems;
        
        private IScreenController screenController;
        private Int32 selectedIndex;
        private Inventory inventory;

        private TimeSpan lastMovementInput;
        private TimeSpan lastActionInput;
        private TimeSpan lastSetInput;


        public InventoryScreen(IScreenController screenController)
        {
            this.Controls = new ControlCollection();
            this.inventoryItems = new List<InventoryItem>();
            this.screenController = screenController;

            this.inventory = null;
            selectedIndex = -1;
        }


        public override void ActivateScreen()
        {
            this.Controls.Clear();
            this.inventoryItems.Clear();

            this.inventory = screenController.GameData.GameState.Player.Inventory;

            playerHud = new PlayerHud(this.screenController.RawContentManager, 0, 0, this.screenController.Resolution.GameWidth, TileSet.DRAW_HEIGHT);
            playerHud.Player = this.screenController.GameData.GameState.Player;
            Controls.Add(playerHud);

            selectedItemDescriptionLabel = new Label()
            {
                Font = this.screenController.RawContentManager.FontRepository.GetContent(@"fonts\Normal"),
                Location = new Rectangle(475, 60, 200, 75),
                CropTextToFitWidth = true,
                Text = ""
            };
            Controls.Add(selectedItemDescriptionLabel);

            slot1ItemDescriptionLabel = new Label()
            {
                Font = this.screenController.RawContentManager.FontRepository.GetContent(@"fonts\Normal"),
                Location = new Rectangle(475, 175, 200, 88),
                CropTextToFitWidth = true,
                Text = ""
            };
            Controls.Add(slot1ItemDescriptionLabel);

            slot2ItemDescriptionLabel = new Label()
            {
                Font = this.screenController.RawContentManager.FontRepository.GetContent(@"fonts\Normal"),
                Location = new Rectangle(475, 265, 200, 88),
                CropTextToFitWidth = true,
                Text = ""
            };
            Controls.Add(slot2ItemDescriptionLabel);

            playerStatsLabel = new Label()
            {
                Font = this.screenController.RawContentManager.FontRepository.GetContent(@"fonts\Normal"),
                Location = new Rectangle(320, 175, 110, 185),
                Text = ""
            };
            Controls.Add(playerStatsLabel);

            miniMapViewer = new MiniMapViewer()
            {
                Location = new Rectangle(320, 56, 112, 75),
                BackgroundTexture = this.screenController.RawContentManager.TextureRepository.GetContent(@"textures\ui\mapViewer-bg"),
                ActiveCellTexture = this.screenController.RawContentManager.TextureRepository.GetContent(@"textures\ui\mapViewer-activeCell"),
                CellTexture = this.screenController.RawContentManager.TextureRepository.GetContent(@"textures\ui\mapViewer-cell"),
                WorldMap = this.screenController.GameData.WorldMaps.GetContent(this.screenController.GameData.GameState.Player.WorldPosition.WorldMapKey),
                Player = this.screenController.GameData.GameState.Player
            };

            Controls.Add(miniMapViewer);

            for (Int32 i = 0; i < this.inventory.InventorySlots.Count; i++)
            {
                InventorySlot slot = this.inventory.InventorySlots[i];
                Int32 ix = 30 + ((i % 2) * 150);
                Int32 iy = 64 + ((i/2) * 48);
                InventoryItem itemControl = new InventoryItem(this.screenController.RawContentManager, ix, iy)
                {
                    InventorySlot = slot
                };

                this.inventoryItems.Add(itemControl);
                this.Controls.Add(itemControl);
            }

            if (inventory.InventorySlots.Count == 0)
            {
                selectedIndex = -1;
            }
            else
            {
                selectedIndex = 0;
                this.inventoryItems[selectedIndex].IsSelected = true;
            }

            UpdateItemLabels();
            UpdateCharacterStatsLabel();

            lastMovementInput = screenController.LastKeyboardInputTime;
            lastActionInput = screenController.LastKeyboardInputTime;
            lastSetInput = screenController.LastKeyboardInputTime;
        }


        public override void Draw(SpriteBatch spriteBatch, GameTime gameTime)
        {
            Texture2D backgroundTexture = this.screenController.RawContentManager.TextureRepository.GetContent(@"textures\ui\inventory-background");
            spriteBatch.Draw(backgroundTexture, new Rectangle(0,0,this.screenController.Resolution.GameWidth,this.screenController.Resolution.GameHeight), Color.White);

            foreach (IControl control in this.Controls)
            {
                control.Draw(spriteBatch, gameTime);
            }
        }


        public override void Update(GameTime gameTime)
        {
            //keyboard
            if ((gameTime.TotalGameTime - lastMovementInput).TotalSeconds >= 0.12)
            {
                if (Keyboard.GetState().IsKeyDown(Keys.Up))
                {
                    MoveSelectedItem(-2);
                    lastMovementInput = gameTime.TotalGameTime;
                }
                else if (Keyboard.GetState().IsKeyDown(Keys.Down))
                {
                    MoveSelectedItem(2);
                    lastMovementInput = gameTime.TotalGameTime;
                }
                else if (Keyboard.GetState().IsKeyDown(Keys.Left))
                {
                    MoveSelectedItem(-1);
                    lastMovementInput = gameTime.TotalGameTime;
                }
                else if (Keyboard.GetState().IsKeyDown(Keys.Right))
                {
                    MoveSelectedItem(1);
                    lastMovementInput = gameTime.TotalGameTime;
                }
            }
            
            if ((gameTime.TotalGameTime - lastSetInput).TotalSeconds >= 0.12)
            {
                if (Keyboard.GetState().IsKeyDown(Keys.X))
                {
                    SetSlot1();
                    lastSetInput = gameTime.TotalGameTime;
                }
                else if (Keyboard.GetState().IsKeyDown(Keys.W))
                {
                    SetSlot2();
                    lastSetInput = gameTime.TotalGameTime;
                }
            }
            
            if ((gameTime.TotalGameTime - lastActionInput).TotalSeconds >= 0.25)
            {
                if (Keyboard.GetState().IsKeyDown(Keys.Enter))
                {
                    lastActionInput = gameTime.TotalGameTime;
                    screenController.LastKeyboardInputTime = gameTime.TotalGameTime;
                    this.screenController.ChangeScreen(ScreenType.Game);
                }
                else if (Keyboard.GetState().IsKeyDown(Keys.Escape))
                {
                    lastActionInput = gameTime.TotalGameTime;
                    screenController.LastKeyboardInputTime = gameTime.TotalGameTime;
                    this.screenController.ChangeScreen(ScreenType.GameMenu);
                }
            }

            //controls
            foreach (IControl control in this.Controls)
            {
                control.Update(gameTime);
            }
        }


        private void MoveSelectedItem(int di)
        {
            Int32 currentIndex = this.selectedIndex;
            
            this.selectedIndex += di;

            if(this.selectedIndex >= this.inventory.InventorySlots.Count)
            {
                Int32 diff = this.selectedIndex - this.inventory.InventorySlots.Count;

                this.selectedIndex = diff;
            }
            else if (this.selectedIndex < 0)
            {
                Int32 diff = this.inventory.InventorySlots.Count + this.selectedIndex;

                this.selectedIndex = diff;
            }

            if(this.selectedIndex >= this.inventory.InventorySlots.Count)
            {
                this.selectedIndex = currentIndex;
                return;
            }
            
            if((currentIndex < 0) || (selectedIndex < 0)) return;
            if (this.inventoryItems.Count == 0) return;

            
            this.inventoryItems[currentIndex].IsSelected = false;
            
            this.inventoryItems[selectedIndex].IsSelected = true;
            UpdateItemLabels();
        }


        private void UpdateCharacterStatsLabel()
        {
            String text = "";
            CharacterStats stats = this.screenController.GameData.GameState.Player.CharacterStats;

            text += "HP:";
            text += "\n";
            text += stats.Health + "/" + stats.MaximumHealth;
            text += "\n\n";
            text += "Atk:";
            text += "\n";
            text += stats.Attack;
            text += "\n\n";
            text += "Def:";
            text += "\n";
            text += stats.Defence;
            text += "\n";

            this.playerStatsLabel.Text = text;
        }


        private void UpdateItemLabels()
        {
            if ((this.selectedIndex >= 0) && (this.selectedIndex < this.inventory.InventorySlots.Count))
                this.selectedItemDescriptionLabel.Text = this.inventoryItems[selectedIndex].InventorySlot?.Item?.Description;
            else
                this.selectedItemDescriptionLabel.Text = "";

            Inventory inventory = this.screenController.GameData.GameState.Player.Inventory;
            if (inventory.Slot1 != null) this.slot1ItemDescriptionLabel.Text = "X:\n" + inventory.Slot1.Item.Description;
            else this.slot1ItemDescriptionLabel.Text = "";

            if (inventory.Slot2 != null) this.slot2ItemDescriptionLabel.Text = "W:\n" + inventory.Slot2.Item.Description;
            else this.slot2ItemDescriptionLabel.Text = "";
        }


        private void SetSlot1()
        {
            InventorySlot tempInv = null;
            InventorySlot tempSlot = null;

            if (selectedIndex < 0) return;

            tempInv = this.inventoryItems[selectedIndex].InventorySlot;
            tempSlot = this.screenController.GameData.GameState.Player.Inventory.Slot1;

            //change model
            this.screenController.GameData.GameState.Player.Inventory.InventorySlots[selectedIndex] = tempSlot;
            this.screenController.GameData.GameState.Player.Inventory.Slot1 = tempInv;

            //change ui
            this.inventoryItems[selectedIndex].InventorySlot = tempSlot;
            UpdateItemLabels();
        }


        private void SetSlot2()
        {
            InventorySlot tempInv = null;
            InventorySlot tempSlot = null;

            if (selectedIndex < 0) return;

            tempInv = this.inventoryItems[selectedIndex].InventorySlot;
            tempSlot = this.screenController.GameData.GameState.Player.Inventory.Slot2;

            //change model
            this.screenController.GameData.GameState.Player.Inventory.InventorySlots[selectedIndex] = tempSlot;
            this.screenController.GameData.GameState.Player.Inventory.Slot2 = tempInv;

            //change ui
            this.inventoryItems[selectedIndex].InventorySlot = tempSlot;
            UpdateItemLabels();
        }


    }
}
