using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using System.IO;
using Microsoft.Xna.Framework.Input;

namespace Slayter
{
    class MapCalculator
    {
        public int[,] map;
        public int rows;
        public int cols;
        public List<int> forbidden;

        public MapCalculator(Texture2D Picture,string csvfile)
        {
            // TODO: Complete member initialization
            this.rows = Picture.Height / 40;
            this.cols = Picture.Width / 40;
            map=new int[rows,cols];
            string[] lines = File.ReadAllLines(csvfile);
            this.CreateMap(lines);
            //path = new List<int[]>();
            forbidden = new List<int>();
        }

        private void CreateMap(String[] lines)
        {
            for (int i = 0; i < lines.Length; i++)
            {
                string[] temp = lines[i].Split(';');
                for (int j = 0; j < temp.Length; j++)
                {
                    map[i, j] = Convert.ToInt32(temp[j]);
                    Console.Out.Write(map[i, j] + " ");
                }
                Console.WriteLine("");
            }
        }

        public List<int[]> DeterminePath(int startX, int startY, int endX, int endY,List<int[]> obstacles,Player player)
        {
            Comparator comp=new Comparator();
            List<int[]> path=new List<int[]>();
            bool[,] mapVisited = new bool[rows, cols];
            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols; j++)
                {
                    mapVisited[i, j] = false;
                }
            }
            List<Cell> opened = new List<Cell>();
            List<Cell> list2 = new List<Cell>();
            Cell temp;
            opened.Add(new Cell(startX, startY, 0, 1, null, Direction.Null));
            List<int[]> coor = new List<int[]>();
            while (opened.Count != 0)
            {
                coor.Clear();
                for (int i = 0; i < opened.Count; i++)
                {
                    Cell cell = opened[i];
                    if (cell.Activate())
                    {

                        coor.Add(new int[2] { cell.x, cell.y });
                        if (cell.x > 0 && !mapVisited[cell.x - 1, cell.y] && !forbidden.Contains(map[cell.x - 1, cell.y]) 
                            && !obstacles.Contains(new int[2] {cell.x - 1, cell.y},comp) && !player.checkIfUncovered(cell.x-1,cell.y))
                        {
                            coor.Add(new int[2] { cell.x - 1, cell.y });
                            temp = new Cell(cell.x - 1, cell.y, cell.path + map[cell.x - 1, cell.y] + 1, map[cell.x - 1, cell.y] + 1, cell, Direction.Up);
                            checkForMatchingCellsAndAdd(list2, temp);
                        }
                        if (cell.y > 0 && !mapVisited[cell.x, cell.y - 1] && !forbidden.Contains(map[cell.x, cell.y - 1])
                            && !obstacles.Contains(new int[2] { cell.x, cell.y - 1 }, comp) && !player.checkIfUncovered(cell.x, cell.y-1))
                        {
                            temp = new Cell(cell.x, cell.y - 1, cell.path + map[cell.x, cell.y - 1] + 1, map[cell.x, cell.y - 1] + 1, cell, Direction.Left);
                            coor.Add(new int[2] { cell.x, cell.y - 1 });
                            checkForMatchingCellsAndAdd(list2, temp);
                        }
                        if (cell.x < rows - 1 && !mapVisited[cell.x + 1, cell.y] && !forbidden.Contains(map[cell.x + 1, cell.y])
                            && !obstacles.Contains(new int[2] { cell.x + 1, cell.y }, comp) && !player.checkIfUncovered(cell.x + 1, cell.y))
                        {
                            temp = new Cell(cell.x + 1, cell.y, cell.path + map[cell.x + 1, cell.y] + 1, map[cell.x + 1, cell.y] + 1, cell, Direction.Down);
                            coor.Add(new int[2] { cell.x + 1, cell.y });
                            checkForMatchingCellsAndAdd(list2, temp);
                        }
                        if (cell.y < cols - 1 && !mapVisited[cell.x, cell.y + 1] && !forbidden.Contains(map[cell.x, cell.y + 1])
                            && !obstacles.Contains(new int[2] { cell.x, cell.y + 1 }, comp) && !player.checkIfUncovered(cell.x, cell.y+1))
                        {
                            temp = new Cell(cell.x, cell.y + 1, cell.path + map[cell.x, cell.y + 1] + 1, map[cell.x, cell.y + 1] + 1, cell, Direction.Right);
                            coor.Add(new int[2] { cell.x, cell.y + 1 });
                            checkForMatchingCellsAndAdd(list2, temp);
                        }
                    }
                    else
                    {
                        list2.Add(cell);
                    }
                }
                for (int i = 0; i < list2.Count; i++)
                {
                    Cell cell = list2[i];
                    if (cell.x == endX && cell.y == endY)
                    {
                        path.Clear();
                        while (!cell.CheckFatherForNull())
                        {
                            path.Add(new int[2] { cell.y, cell.x });
                            cell = cell.father;

                        }
                        path.Reverse();
                        return path;
                    }
                }


                for (int i = 0; i < coor.Count; i++)
                {
                    mapVisited[coor[i][0], coor[i][1]] = true;
                }
                opened = new List<Cell>(list2);
                list2.Clear();
            }
            return null;
        }

        private void checkForMatchingCellsAndAdd(List<Cell> list2, Cell temp)
        {
            if (!list2.Contains(temp))
            {
                list2.Add(temp); ;
                return;
            }
            Cell temp2 = list2.Find(delegate(Cell c)
            {
                return c.Equals(temp);
            });
            if (temp.path < temp2.path)
            {
                list2.Remove(temp2);
                list2.Add(temp);
            }
        }
    }
}
