using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Xml;
using System.IO;
using Vortex.IO;

namespace Vortex.Demo.Pacman {

    ///<summary>Enumeration of possible map items</summary>
    public enum MapItemType : short {
        Blank = 0,
        Dot = 1,
        SuperDot = 2,
        Wall = 3,
        PlayerStartPos = 4,
        JumpPoint1 = 5,
        JumpPoint2 = 6,
        Ghost = 7
    };

    ///<summary>Contains information about specific level</summary>
    class LevelInfo {
        const char MAP_BLANK                = ' ';
        const char MAP_DOT                  = '.';
        const char MAP_SUPERDOT             = 'o';
        const char MAP_WALL                 = '#';
        const char MAP_PLAYERSTARTPOS       = 'S';
        const char MAP_JUMPPOINT1           = '{';
        const char MAP_JUMPPOINT2           = '}';

        MapItemType[,] m_map;
        Point m_playerStartPos;
        List<Point> m_Ghosts = new List<Point>();
        Point[] m_JumpPoints = new Point[2];

        public LevelInfo (int levelNumber) {
			using (Stream stream = new ResourceFileInfo("{data}/levels/" + levelNumber + ".xml").OpenStream()) {

				XmlDocument document = new XmlDocument();
				document.Load(stream);

				XmlNode mapNode = document.GetElementsByTagName("Map")[0];
				int mapWidth = Int32.Parse(mapNode.Attributes["Width"].Value);
				int mapHeight = Int32.Parse(mapNode.Attributes["Height"].Value);

				m_map = new MapItemType[mapWidth, mapHeight];

				int rowNumber = 0;
				foreach (XmlNode rowNode in mapNode.SelectNodes("Row")) {
					FillMapRow(rowNode.InnerText, rowNumber++);
				}
			}
        }

        public MapItemType[,] Map {
            get { return m_map; }
        }

        public Point PlayerStartPosition {
            get { return m_playerStartPos; }
        }

        public List<Point> GhostStartPositions {
            get { return m_Ghosts; }
        }

        private void FillMapRow(string mapRowString, int rowNo) {
            int colNo = 0;
            foreach (char ch in mapRowString.ToCharArray()) {
                if (ch >= '1' && ch < '9') {
                    m_Ghosts.Add(new Point(colNo, rowNo));
                    m_map[colNo++, rowNo] = MapItemType.Blank;
                }
                else {
                    MapItemType cellType = CharToCellItemType(ch);
                    if (cellType == MapItemType.PlayerStartPos) {
                        m_playerStartPos = new Point(colNo, rowNo);
                        cellType = MapItemType.Blank;
                    }
                    m_map[colNo++, rowNo] = cellType;
                }
               
                
            }
        }

        private MapItemType CharToCellItemType(char ch) {
            if (ch == MAP_BLANK) {
                return MapItemType.Blank;
            } 
            else if (ch == MAP_DOT) {
                return MapItemType.Dot;
            }
            else if (ch == MAP_SUPERDOT) {
                return MapItemType.SuperDot;
            }
            else if (ch == MAP_WALL) {
                return MapItemType.Wall;
            }
            else if (ch == MAP_PLAYERSTARTPOS) {
                return MapItemType.PlayerStartPos;
            }
            else if (ch == MAP_JUMPPOINT1) {
                return MapItemType.JumpPoint1;
            }
            else if (ch == MAP_JUMPPOINT2) {
                return MapItemType.JumpPoint2;
            }
            throw new LevelLoadException("Invalid map character: '{0}'", ch);
        }

    }

}
