using System;
using System.Collections.Generic;
using System.Text;
using ECOT.Engine;
using ECOT.Game.Buildings;
using ECOT.Game.Tools;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using ECOT.Engine.Statistics;

namespace ECOT.Game
{
    public delegate void CityEventHandler(City city);
    // pour les event lors de la disponibilité des minijeux
    public delegate void MiniGameActivatedEventHandler(City city);

    // TODO: bouger ca dans un endroit plus générique
    public enum ExtendState
    {
        Hidden,
        Inflating,
        Visible,
        Deflating
    }

    /// <summary>
    /// Classe qui renseigne comment la ville doit s'afficher à l'écran, si certaines parties doivent s'afficher ou non,
    /// ou si des effets graphiques doivent être appliqués. Pour résumer tout ce qui altère le rendu d'une ville doit
    /// être référencé dans cette classe.
    /// </summary>
    public class CityRenderState
    {
        public bool DrawPollutionClouds = true;
        /// <summary>
        /// Dessine ou non l'aire d'influence.
        /// </summary>
        public ExtendState drawAreaState = ExtendState.Hidden;
        public float DrawAreaProgress = 0.0f;

        public bool DrawStreets = true;

        public bool DrawArea
        {
            get { return (this.drawAreaState != ExtendState.Hidden); }
            set
            {
                if (value && this.drawAreaState == ExtendState.Visible ||
                    !value && this.drawAreaState == ExtendState.Hidden) return;

                if (value)
                {
                    this.drawAreaState = ExtendState.Inflating;
                    this.DrawAreaProgress = 0.0f;
                }
                else
                {
                    this.drawAreaState = ExtendState.Deflating;
                    this.DrawAreaProgress = 0.2f;
                }
            }
        }
        /// <summary>
        /// Dessine ou non la grille.
        /// </summary>
        public bool DrawGrid = false;
        /// <summary>
        /// Dessine le rectangle englobant (DEBUG).
        /// </summary>
        // Obligé d'enlever le debug... :s
        public bool DrawBoudingRectangle = false;
    }



    /// <summary>
    /// Cette classe représente un ville du jeu.
    /// </summary>
    public class City : Levelable, ISelectable
    {

        #region Internal

        /// <summary>
        /// Groupe de variable d'un même domaine (eau, nourriture, etc...)
        /// </summary>
        public class Domain
        {
            /// <summary>
            /// Nom du domaine.
            /// </summary>
            public string Name = null;
            /// <summary>
            /// Besoin.
            /// </summary>
            public Variable Need = new Variable();
            /// <summary>
            /// Disponible.
            /// </summary>
            public Variable Available = new Variable();
            /// <summary>
            /// Production Actuelle des bâtiments d'une ville
            /// </summary>
            public Variable Production = new Variable(0.0, new SumVariableComputer());
            /// <summary>
            /// Ratio besoin / disponible.
            /// </summary>
            public Variable Ratio = new Variable();
            /// <summary>
            /// Poids relatif à l'importance du domaine pour le calcul d'autre variables.
            /// </summary>
            public int Weight;
            /// <summary>
            /// Nombre de bâtiments construits pour ce domaine.
            /// </summary>
            public int BuildingNumber = 0;

            public Domain(string domainName)
            {
                this.Name = domainName;
            }

            public void NameVariables(string cityName)
            {
                string formatted = cityName.Substring(0, 3).ToLower();
            }

            public void ConstructDomain(City city, BuildingCategory bc, Variable needOperation, VariableComputeMode stockMode)
            {
                // Disponible
                this.Available.Depend(this.Production);
                
                // Consommation
                this.Need.Depend(needOperation);
                // Ratio
                this.Ratio.Depend(this.Available / this.Need);
                this.Ratio.AfterCompute += GenericHandlers.Saturate;
            }

            public void RegisterDomain()
            {
                // FIXME: obligé de tout enregistrer sinon ce n'est pas pris en compte
                GameController.Instance.RegisterVariable(SimulationPool.Daily, this.Production);
                GameController.Instance.RegisterVariable(SimulationPool.Daily, this.Available);
                GameController.Instance.RegisterVariable(SimulationPool.Daily, this.Need);
                GameController.Instance.RegisterVariable(SimulationPool.Daily, this.Ratio);
            }
        }

        private enum StreetsType
        {
/*
            Top = 0x00000000,
            Bottom = 0x00010000,
            Right = 0x00020000,
            Left = 0x00030000,
            LeftTop = 0x00000001,
            TopRight = 0x00010001,
            BottomLeft = 0x00020001,
            RightBottom = 0x00030001,
            BottomLeftTop = 0x00000002,
            LeftTopRight = 0x00010002,
            TopRightBottom = 0x00020002,
            RightBottomLeft = 0x00030002,
 */
            Full = 0x00000003,

            None = -1
        }

        #endregion

        private Color highlightSlotColor = Color.White;

        private bool isEvolution = false;
        private bool flipEvolution = false;
        private int timeflip = 0;
        private int limitTimeFlip = 250;
        private int totaltimeflip = 0;

        public bool IsEvolution
        {
            get { return this.isEvolution; }
            set { this.isEvolution = value; }
        }

        #region Membres

        /// <summary>
        /// Nom de la ville.
        /// </summary>
        private string name = string.Empty;
        /// <summary>
        /// Aire d'influence de la ville.
        /// </summary>
        private int area;

        /// <summary>
        /// Domaine relatif à l'eau.
        /// </summary>
        private Domain waterDomain;
        /// <summary>
        /// Domaine relatif à la nourriture.
        /// </summary>
        private Domain foodDomain;
        /// <summary>
        /// Domaine relatif à l'énergie.
        /// </summary>
        private Domain energyDomain;

        private int educationBuildingNumber = 0;

        /// <summary>
        /// Domaine relatif au travail.
        /// </summary>
        private Domain schoolDomain;
        private Domain universityDomain;
        private Domain stadiumDomain;
        private Domain libraryDomain;

        /// <summary>
        /// Nombre de bâtiments ecologique.
        /// </summary>
        private int ecologyBuildingNumber = 0;



        /// <summary>
        /// Position de la ville dans les coordonnées de l'écran.
        /// </summary>
        private Vector2 position;
        /// <summary>
        /// Offset de décalage vers le haut utilisé pour replacer le bâtiment sur la bonne case.
        /// <remarks>Les textures des villes peuvent ne pas être de taille égale, en tout cas pendant les tests.</remarks>
        /// </summary>
        private Vector2 offset;
        /// <summary>
        /// Texture utilisée pour afficher l'image de la ville.
        /// </summary>
        private Texture2D texture;
        private int textureOffset;

        public static Texture2D StreetsTexture;

        /// <summary>
        /// Nom du maire réel.
        /// </summary>
        private string mayor;
        /// <summary>
        /// Surface réelle de la ville en km².
        /// </summary>
        private int surface;
        /// <summary>
        /// Population réelle de la ville en million d'habitants.
        /// </summary>
        private int realPopulation;
        /// <summary>
        /// Nom de la région de la ville.
        /// </summary>
        private string province;
        /// <summary>
        /// Liste des bâtiments actuels de la ville.
        /// </summary>
        private List<CityBuilding> buildings = new List<CityBuilding>();
        /// <summary>
        /// Liste des bâtiment d'un type particulier d'une ville
        /// </summary>
        public List<Building> buildingsSpecifique = new List<Building>();
        /// <summary>
        /// Emplacements disponibles pour les nouveaux bâtiments.
        /// </summary>
        private bool[][] availableSlots = null;
        private bool[][] hightlightSlots = null;
        /// <summary>
        /// Etat de rendu de la ville.
        /// <see cref="RenderState"/>
        /// </summary>
        private CityRenderState renderState = new CityRenderState();
        private static Texture2D infectedTexture = null;

        private static Texture2D[] gamesTexture = new Texture2D[3];

        private bool enabled = true;
        private bool selected = false;
        private bool hover = false;

        private bool[] games = new bool[3];

        private StreetsType[][] streets = null;

        /// <summary>
        /// Niveau actuel de la ville.
        /// </summary>
        private Variable levelVar = new Variable(0);
        /// <summary>
        /// Réputation actuelle de la ville.
        /// </summary>
        private Variable reputation = new Variable(0);
        /// <summary>
        /// Population actuelle de la ville.
        /// </summary>
        private Variable population = new Variable(0, new SumVariableComputer(VariableComputeMode.IncrementalSum));
        
        #endregion

        #region Initialisation

        public City()
        {
            // Crée les slots
            this.CreateSlots();

            // Crée les domaines
            this.waterDomain = new Domain("water");
            this.foodDomain = new Domain("food");
            this.energyDomain = new Domain("energy");
            // Education
            this.schoolDomain = new Domain("school");
            this.universityDomain = new Domain("university");
            this.stadiumDomain = new Domain("stadium");
            this.libraryDomain = new Domain("library");

            // Crée les levels
            this.AddLevel(new CityLevel1(this));
            this.AddLevel(new CityLevel2(this));
            this.AddLevel(new CityLevel3(this));

            // By default, enables the city
            this.Enable();

            this.texture = Kernel.Instance.Medias.Get<Texture2D>(@"Textures\Cities\Cities");
            this.offset = new Vector2(0f, 64.0f);
        }


        private void CreateSlots()
        {
            this.Area = 1;

            // Taille des slots (doit correspondre à la taille maximum - c'est pourquoi on multiplie le area par 3).
            int width = Rules.Cities.Size.Width + 2 * Rules.Cities.MaxDrawArea;
            int height = Rules.Cities.Size.Height + 2 * Rules.Cities.MaxDrawArea;

            // Création des tableaux
            this.availableSlots = new bool[width][];
            this.hightlightSlots = new bool[width][];
            this.streets = new StreetsType[width][];
            for (int i = 0; i < width; i++)
            {
                this.availableSlots[i] = new bool[height];
                this.hightlightSlots[i] = new bool[height];
                this.streets[i] = new StreetsType[height];
                for (int j = 0; j < height; j++)
                {
                    this.availableSlots[i][j] = true;
                    this.hightlightSlots[i][j] = false;
                    this.streets[i][j] = StreetsType.None;
                }
            }

            // Marque les slots occupés par la ville comme occupés
            this.availableSlots[Rules.Cities.MaxDrawArea][Rules.Cities.MaxDrawArea] =
            this.availableSlots[Rules.Cities.MaxDrawArea + 1][Rules.Cities.MaxDrawArea] =
            this.availableSlots[Rules.Cities.MaxDrawArea][Rules.Cities.MaxDrawArea + 1] =
            this.availableSlots[Rules.Cities.MaxDrawArea + 1][Rules.Cities.MaxDrawArea + 1] = false;

            // Définit les routes de la ville
            this.streets[Rules.Cities.MaxDrawArea][Rules.Cities.MaxDrawArea] =
            this.streets[Rules.Cities.MaxDrawArea + 1][Rules.Cities.MaxDrawArea] =
            this.streets[Rules.Cities.MaxDrawArea][Rules.Cities.MaxDrawArea + 1] =
            this.streets[Rules.Cities.MaxDrawArea + 1][Rules.Cities.MaxDrawArea + 1] = StreetsType.Full;
        }



        #endregion

        #region Properties

        #region Général

        public bool Selected
        {
            get { return this.selected; }
        }



        public string Name
        {
            get { return this.name; }
            set
            {
                this.name = value;
                string formatted = value.Substring(0, 3).ToLower();
            }
        }



        /// <summary>
        /// Assigne ou récupère le niveau de la ville. Pour faire changer de niveau à une ville il faut absoluement passer
        /// par cette propriété qui s'occupe du leveling de la ville automatiquement.
        /// <see cref="City.Level"/>
        /// </summary>



        public CityBuilding[] Buildings
        {
            get { return this.buildings.ToArray(); }
        }

        public int Area
        {
            get { return this.area; }
            set { this.area = value; }
        }

        public Vector2 Position
        {
            get { float tile = 64;
                return new Vector2((int)(this.position.X / tile), (int)(this.position.Y / 64)); }
            set
            {
                this.position = new Vector2(value.X * 64, value.Y * 64);
            }
        }

        public Vector2 ScreenPosition
        {
            get { return this.position; }
            set { this.position = value; }
        }

        public int TextureOffset
        {
            get { return this.textureOffset; }
            set { this.textureOffset = value; }
        }

        public CityRenderState RenderState
        {
            get { return this.renderState; }
        }

        #endregion

        #region Statistiques

        public Variable Population
        {
            get { return this.population; }
        }
        public Variable LevelVariable
        {
            get { return this.levelVar; }
        }
        public Variable Reputation
        {
            get { return this.reputation; }
        }
        public Domain WaterDomain
        {
            get { return this.waterDomain; }
        }

        public Domain FoodDomain
        {
            get { return this.foodDomain; }
        }
        public Domain EnergyDomain
        {
            get { return this.energyDomain; }
        }

        public int EducationBuildingNumber
        {
            get { return this.educationBuildingNumber; }
            set { this.educationBuildingNumber = value; }
        }

        public Domain SchoolDomain
        {
            get { return this.schoolDomain; }
        }

        public Domain UniversityDomain
        {
            get { return this.universityDomain; }
        }

        public Domain StadiumDomain
        {
            get { return this.stadiumDomain; }
        }

        public Domain LibraryDomain
        {
            get { return this.libraryDomain; }
        }

        public int EcologyBuildingNumber
        {
            get { return this.ecologyBuildingNumber; }
        }



        #endregion

        #region Culture générale

        public string Mayor
        {
            get { return this.mayor; }
            set { this.mayor = value; }
        }

        public int RealSurface
        {
            get { return this.surface; }
            set { this.surface = value; }
        }

        public int RealPopulation
        {
            get { return this.realPopulation; }
            set { this.realPopulation = value; }
        }

        public string Province
        {
            get { return this.province; }
            set { this.province = value; }
        }

        #endregion


        public bool getGames(int i) { return this.games[i]; }
        public void setGames(int i, bool b)
        {
            this.games[i] = b;

        }

        public bool Enabled
        {
            get { return this.enabled; }
            set
            {
                if (this.enabled == value) return;

                this.enabled = value;
                if (value)
                    this.Enable();
                else
                    this.Disable();
            }
        }

        public static Texture2D InfectedTexture
        {
            get { return City.infectedTexture; }
            set { City.infectedTexture = value; }
        }

        public static void setMiniGameTexture(int i, Texture2D tex)
        {
            City.gamesTexture[i] = tex;
        }
        public static Texture2D getMiniGameTexture(int i)
        {
            return City.gamesTexture[i];
        }
        #endregion

        #region Méthodes

        #region Bâtiments

        public void AddBuilding(Vector2 slotPos, CityBuilding building)
        {
                   this.buildings.Add(building);
                   building.AttachTo(this, slotPos); 
            this.availableSlots[(int)slotPos.X][(int)slotPos.Y] = false;

        }

        private void UpdateStreetsTopology(int x, int y)
        {
            // Applique un pourtour à l'endroit du bâtiment
            this.streets[x][y] = StreetsType.Full;
        }

        public void RemoveBuilding(CityBuilding building)
        {
            Vector2 slotPos = building.SlotPosition;
            this.availableSlots[(int)slotPos.X][(int)slotPos.Y] = true;
            this.streets[(int)slotPos.X][(int)slotPos.Y] = StreetsType.None;
            this.buildings.Remove(building);
            this.UpdateBuildingNumber(building, -1);
        }

        private void UpdateBuildingNumber(CityBuilding building, int mod)
        {
            switch (building.Category)
            {
                case BuildingCategory.Energy:
                    this.EnergyDomain.BuildingNumber += mod;
                    break;
                case BuildingCategory.Education:
                    this.educationBuildingNumber += mod;
                    break;
                case BuildingCategory.Ecology:
                    this.ecologyBuildingNumber += mod;
                    break;
            }
        }

        #endregion

        #region Outils

        public bool InArea(Vector2 cursorPos)
        {
            Vector2 cityPos = this.Position;
            if ((cursorPos.X >= cityPos.X - this.area) && (cursorPos.X <= cityPos.X + this.area + Rules.Cities.Size.Width / 2) &&
                (cursorPos.Y >= cityPos.Y - this.area - Rules.Cities.Size.Height / 2) && (cursorPos.Y <= cityPos.Y + this.area))
                return true;
            return false;
        }

        public bool IsSlotAvailable(Vector2 slotPos)
        {
            int limit = Rules.Cities.MaxDrawArea - this.area;

            // Vérifie la validité du slot
            if (slotPos.X < limit || slotPos.Y < limit ||
                slotPos.X >= this.availableSlots.Length - limit || slotPos.Y >= this.availableSlots[0].Length - limit)
                return false;

            // Vérifie qu'il n'y a pas déjà un autre bâtiment
            return this.availableSlots[(int)slotPos.X][(int)slotPos.Y];
        }

        public Vector2 ToSlot(Vector2 pos)
        {
            Vector2 cPos = this.Position;
            Vector2 slot = new Vector2(
                pos.X - cPos.X + Rules.Cities.MaxDrawArea,
                pos.Y - cPos.Y + Rules.Cities.MaxDrawArea + Rules.Cities.Size.Width / 2);
            return slot;
        }

        public void HighlightSlot(Vector2 slotPos, bool highlight)
        {
            this.HighlightSlot(slotPos, highlight, Color.White);
        }

        public void HighlightSlot(Vector2 slotPos, bool highlight, Color color)
        {
            // Vérifie la validité du slot
            if (slotPos.X < 0.0f || slotPos.Y < 0.0f ||
                slotPos.X >= this.availableSlots.Length || slotPos.Y >= this.availableSlots[0].Length)
                return;

            this.hightlightSlots[(int)slotPos.X][(int)slotPos.Y] = highlight;
            this.highlightSlotColor = color;
        }

        #endregion

        #region Rendu

        public void Render(GameTime gameTime)
        {
            SpriteBatch spriteBatch = Kernel.Instance.SpriteBatch;
            spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None, Kernel.Instance.Camera.TransformMatrix);
            
            // Dessine l'aire d'influence
            if (this.renderState.drawAreaState != ExtendState.Hidden)
            {
                DrawCityInfluenceZone();
            }
            else if (this.hover)
            {
                DrawCityInfluenceHover();
            }

            // Dessine la grille            
            if (this.renderState.DrawGrid)
            {
                DrawCityGrid();
            }            

            // Dessine les bâtiments de la ville
            for (int i = 0; i < this.buildings.Count; i++)
                this.buildings[i].Render(gameTime);
            
            // Dessine la plate-forme sous la ville
            spriteBatch.Draw(
                City.StreetsTexture,
                new Rectangle((int)(this.position.X - this.offset.X - 9), (int)(this.position.Y - this.offset.Y - 9), 146, 146),
                new Rectangle(257, 257, 62, 62),
                this.enabled ? Color.White : Color.Gray);



            // Si la ville est en train de passer au level supérieur
            Rectangle recText;
            if (this.isEvolution)
            {
                if (this.flipEvolution)
                    recText = new Rectangle((this.Level - 2) * 128, this.textureOffset * 128, 128, 128);
                else
                    recText = new Rectangle((this.Level - 1) * 128, this.textureOffset * 128, 128, 128);

                this.timeflip += Kernel.Instance.Time.ElapsedGameTime.Milliseconds;
                this.totaltimeflip += Kernel.Instance.Time.ElapsedGameTime.Milliseconds;
                if (timeflip >= this.limitTimeFlip)
                {
                    this.flipEvolution = !flipEvolution;
                    timeflip = 0;
                    this.limitTimeFlip -= 15;
                    if (this.limitTimeFlip < 45)
                        this.limitTimeFlip = 45;
                }
                if (this.totaltimeflip > 3500)
                {
                    this.isEvolution = false;
                    this.totaltimeflip = 0;
                    this.limitTimeFlip = 250;
                }
            }
            else
                recText = new Rectangle((this.Level - 1) * 128, this.textureOffset * 128, 128, 128);

            spriteBatch.Draw(this.texture,
                this.position - this.offset,
                recText, this.enabled ? Color.White : Color.Gray,
                0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.0f);
            
             spriteBatch.End();
        }
        #endregion

        private void Enable()
        {
            this.Enabled = true;
        }

        private void Disable()
        {
            this.Enabled = false;
        }

        public void DayChanged()
        {
            // Met à jour le niveau de la ville
            this.UpdateLevel();

            // On utilise un for ici ca le bâtiment peut changer pendant un leveling
            for (int i = 0; i < this.buildings.Count; i++)
                this.buildings[i].DayChanged();
        }


        #endregion


        #region ISelectable Membres

        public event CityEventHandler OnFocus;
        public event CityEventHandler OnBlur;

        public void Hover()
        {
            this.hover = true;
        }

        public void Out()
        {
            this.hover =  false;
        }

        public void Focus()
        {
            this.selected = this.renderState.DrawArea = true;
            this.renderState.DrawAreaProgress = 0.0f;

            if (this.OnFocus != null)
                this.OnFocus(this);
        }

        public void Blur()
        {
            this.selected = this.renderState.DrawArea = false;

            if (this.OnBlur != null)
                this.OnBlur(this);
        }

        public bool IsSelected(Vector2 pos)
        {
            Vector2 p = this.Position;
            return ((pos.X >= p.X) && (pos.X < p.X + Rules.Cities.Size.Width) &&
                (pos.Y <= p.Y) && (pos.Y > p.Y - Rules.Cities.Size.Height));
        }

        /// <summary>
        /// Dessine la zone "constructible" 
        /// </summary>
        public void DrawCityInfluenceHover()
        {
            SpriteBatch spriteBatch = Kernel.Instance.SpriteBatch;

            int left = (int)(this.position.X - (this.area * 64));
            int top = (int)(this.position.Y - ((this.area + Rules.Cities.Size.Height / 2) * 64));

            // Aire
            spriteBatch.Draw(
                this.texture,
                new Rectangle(left, top,
                    (2 * this.area + Rules.Cities.Size.Width) * 64, (2 * this.area + Rules.Cities.Size.Height) * 64),
                new Rectangle(128, 768, 128, 128),
                new Color(255, 255, 255, 125));
        }
        /// <summary>
        /// Dessine la zone "constructible" d'une ville
        /// </summary>
        public void DrawCityInfluenceZone()
        {
            SpriteBatch spriteBatch = Kernel.Instance.SpriteBatch;

                if (this.renderState.drawAreaState == ExtendState.Inflating)
                {
                    if (this.renderState.DrawAreaProgress < 0.2f)
                    {
                        this.renderState.DrawAreaProgress += Kernel.Instance.Time.ElapsedGameTime.Milliseconds / 1000.0f;
                        if (this.renderState.DrawAreaProgress > 0.2f)
                        {
                            this.renderState.DrawAreaProgress = 0.2f;
                            this.renderState.drawAreaState = ExtendState.Visible;
                        }
                    }
                }
                else if (this.renderState.drawAreaState == ExtendState.Deflating)
                {
                    if (this.renderState.DrawAreaProgress > 0.0f)
                    {
                        this.renderState.DrawAreaProgress -= Kernel.Instance.Time.ElapsedGameTime.Milliseconds / 1000.0f;
                        if (this.renderState.DrawAreaProgress < 0.0f)
                        {
                            this.renderState.DrawAreaProgress = 0.0f;
                            this.renderState.drawAreaState = ExtendState.Hidden;
                        }
                    }
                }

                float progress = this.renderState.DrawAreaProgress / 0.2f;

                int left = (int)(this.position.X - (this.area * 64) * progress + (1 - progress) * 64);
                int top = (int)(this.position.Y - ((this.area + Rules.Cities.Size.Height / 2) * 64) * progress);

                if (this.enabled)
                    spriteBatch.Draw(
                        this.texture,
                        new Rectangle(left, top,
                            (int)((2 * this.area + Rules.Cities.Size.Width) * 64 * progress), (int)((2 * this.area + Rules.Cities.Size.Height) * 64 * progress)),
                        new Rectangle(128, 768, 128, 128),
                        new Color(0, 255, 0, (byte)(255 * progress)));

        }        
        /// <summary>
        ///  Dessine une grille des cases de la ville
        /// </summary>
        public void DrawCityGrid()
        {
                int left = (int)this.position.X - this.area * 64;
                int top = (int)this.position.Y - (this.area + Rules.Cities.Size.Height / 2) * 64;
                int limit = Rules.Cities.MaxDrawArea - this.area;
                SpriteBatch spriteBatch = Kernel.Instance.SpriteBatch;

                for (int x = left, i = limit;
                    x < left + (2 * this.area + Rules.Cities.Size.Width) * 64;
                    x += 64, i++)
                    for (int y = top, j = limit;
                        y < top + (2 * this.area + Rules.Cities.Size.Height) * 64;
                        y += 64, j++)
                    {
                        if (x >= this.position.X && x <= this.position.X + 64 &&
                            y >= this.position.Y - 64 && y <= this.position.Y) continue;

                        if (this.enabled)
                            spriteBatch.Draw(
                                this.texture,
                                new Rectangle(x, y, 64, 64),
                                new Rectangle(128, 768, 128, 128),
                                (this.hightlightSlots[i][j] ? this.highlightSlotColor : new Color(255, 255, 255, 125)));
                    }
        }       


        #endregion

    }
}
