using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using TestBoids.Entities;

namespace TestBoids.Scene
{
    public class Grid
    {
        float m_cellsize;
        public float Cellsize
        {
            get { return m_cellsize; }
        }

        IDictionary<Point, GridCell> m_gridCells;
        public IDictionary<Point, GridCell> GridCells
        {
            get { return m_gridCells; }
            set { m_gridCells = value; }
        }
        IList<Entity> entityList;
        public IList<Entity> EntityList
        {
            get { return entityList; }
            set { entityList = value; }
        }

        public Grid(float cellSize)
        {
            m_cellsize = cellSize;

            m_gridCells = new Dictionary<Point, GridCell>();
            entityList = new List<Entity>();
        }

        public void AddEntity(Entity e)
        {
            Point gridIndex;
            gridIndex.X = (int)Math.Floor(e.Position.X / m_cellsize);
            gridIndex.Y = (int)Math.Floor(e.Position.Y / m_cellsize);

            GridCell cell;
            if (!m_gridCells.TryGetValue(gridIndex, out cell))
            {
                cell = new GridCell();
                m_gridCells.Add(gridIndex, cell);
            }
            cell.EntityList.Add(e);
            entityList.Add(e);
        }

        public void RemoveEntity(Entity e)
        {
            Point gridIndex;
            gridIndex.X = (int)Math.Floor(e.Position.X / m_cellsize);
            gridIndex.Y = (int)Math.Floor(e.Position.Y / m_cellsize);

            entityList.Remove(e);

            GridCell cell;
            m_gridCells.TryGetValue(gridIndex, out cell);
            if (cell != null)
            {
                cell.EntityList.Remove(e);
                if (cell.EntityList.Count == 0)
                {
                    m_gridCells.Remove(gridIndex);
                }
            }
        }

        public void UpdatePosition(Entity e, Vector2 newPos)
        {
            Point gridIndex;
            gridIndex.X = (int)Math.Floor(e.Position.X / m_cellsize);
            gridIndex.Y = (int)Math.Floor(e.Position.Y / m_cellsize);
            GridCell cell;
            m_gridCells.TryGetValue(gridIndex, out cell);

            if (cell != null)
            {
                if (cell.EntityList.Contains(e))
                {
                    cell.EntityList.Remove(e);
                    if (cell.EntityList.Count == 0)
                    {
                        m_gridCells.Remove(gridIndex);
                    }

                    e.Position = newPos;

                    Point newIndex;
                    newIndex.X = (int)Math.Floor(e.Position.X / m_cellsize);
                    newIndex.Y = (int)Math.Floor(e.Position.Y / m_cellsize);
                    GridCell newCell;
                    if (!m_gridCells.TryGetValue(newIndex, out newCell))
                    {
                        newCell = new GridCell();
                        m_gridCells.Add(newIndex, newCell);
                    }
                    newCell.EntityList.Add(e);
                }
            }
        }
    }
}
