/// <summary>
        /// returns a new character with a selected mode.
        /// </summary>
        /// <param name="mode">Selection mode - the way inwhich the character is selected</param>
        /// <returns></returns>
        /// <exception cref="System.NotImplementedException ">thrown if mode is not implemented</exception>
        public Character NewCharacter(SelectionMethod mode, IEnumerable <CharacterGroup> groups)
        {
            List <Character> characters = Alphabet.GetCharacters(groups);
            Character        c;

            switch (mode)
            {
            case SelectionMethod.Random:
                c = RandomCharacter(characters, CurrentCharacter);
                break;

            case SelectionMethod.Sequential:
                c = SequentialCharacter(characters, CurrentCharacter);
                break;

            default:
                throw new NotImplementedException(String.Format("{0} is not an imlemented selection mode", mode));
            }
            CurrentCharacter = c;
            return(c);
        }
        public Alphabet ParseFile(string filePath)
        {
            // Validating XML
            XmlSchemaSet schemas = new XmlSchemaSet();

            schemas.Add("", "AlphabetFile.xsd");

            XDocument doc       = XDocument.Load(filePath);
            bool      errors    = false;
            string    lastError = "";

            doc.Validate(schemas, (o, e) =>
            {
                lastError = e.Message;
                Console.WriteLine("{0}", e.Message);
                errors = true;
            });

            if (errors)
            {
                throw new System.Xml.XmlException("Loaded XML file does not follow the current XML Schema" + lastError);
            }



            //Parsing XML
            //TODO check version number

            XElement rootElement = doc.Element("alphabet-file");

            Alphabet alphabet = new Alphabet
            {
                AlphabetName = rootElement.Attribute("name") != null?rootElement.Attribute("name").Value : "Unamed Group",
            };



            //META DATA
            List <CharacterMetaData> metaDatas = new List <CharacterMetaData>();
            {
                XElement AlphabetCharacters = rootElement.Element("alphabet-characters-meta-data");

                foreach (XElement eMetaGroup in AlphabetCharacters.Elements())
                {
                    foreach (XElement eMetaData in eMetaGroup.Elements())
                    {
                        CharacterMetaData meta = new CharacterMetaData(eMetaData.Attribute("id").Value,
                                                                       eMetaGroup.Attribute("id").Value,
                                                                       eMetaGroup.Attribute("name").Value,
                                                                       eMetaData.Attribute("name").Value,
                                                                       eMetaData.Attribute("display") != null ? eMetaData.Attribute("display").Value.ToLower() == "true" : false,
                                                                       eMetaData.Attribute("input") != null ? eMetaData.Attribute("input").Value.ToLower() == "true" : false
                                                                       );

                        if (meta.Display)
                        {
                            alphabet.DisplayOptions.Add(meta);
                        }
                        if (meta.Input)
                        {
                            alphabet.InputOptions.Add(meta);
                        }

                        metaDatas.Add(meta);
                    }
                }
            }



            //UI OPTIONS
            {
                XElement options = rootElement.Element("ui-options");
                foreach (CharacterMetaData meta in metaDatas)
                {
                    if (meta.ID == options.Element("display-options").Attribute("defaultMeta").Value)
                    {
                        alphabet.DefaultDisplay = meta;
                    }
                    if (meta.ID == options.Element("input-options").Attribute("defaultMeta").Value)
                    {
                        alphabet.DefaultInput = meta;
                    }
                }
            }

            //Groups
            Dictionary <string, CharacterGroup> groups = new Dictionary <string, CharacterGroup>();

            {
                List <CharacterGroup> rootGroups = new List <CharacterGroup>();
                XElement alphabetClasses         = rootElement.Element("alphabet-classes");
                foreach (XElement eGroup in alphabetClasses.Elements())
                {
                    rootGroups.Add(ParseGroupElement(eGroup));
                }

                //TODO better solution than this


                foreach (CharacterGroup g in rootGroups)
                {
                    groups.Add(g.ID, g);
                    foreach (CharacterGroup c in g.GetAllDescendantsGroups())
                    {
                        groups.Add(c.ID, c);
                    }
                    alphabet.CharacterGroups.Add(g);
                }
                alphabet.RootGroups = rootGroups;
            }



            // Characters
            {
                XElement alphabetCharacters = rootElement.Element("alphabet-characters");
                foreach (XElement eCharacter in alphabetCharacters.Elements())
                {
                    Character character = new Character();
                    foreach (XElement eMeta in eCharacter.Elements())
                    {
                        List <string> value = eMeta.Value.Split(',').ToList();

                        CharacterMetaData metaData = null;
                        //TODO optimise this loop (use dictionary?)
                        foreach (CharacterMetaData meta in metaDatas)
                        {
                            if (meta.ID == eMeta.Attribute("id").Value)
                            {
                                metaData = meta;
                                break;
                            }
                        }
                        if (metaData != null)
                        {
                            character.Data.Add(metaData, value);
                        }
                        else
                        {
                            //TODO proper exception
                            throw new Exception("Meta Data ID Invalid");
                        }
                    }


                    List <string> groupIDs = eCharacter.Attribute("class").Value
                                             .Split(new char[0], StringSplitOptions.RemoveEmptyEntries).ToList();

                    foreach (string groupID in groupIDs)
                    {
                        if (!groups.ContainsKey(groupID))
                        {
                            throw new KeyNotFoundException("key \"" + groupID + "\" was not found in groups");
                        }
                        groups[groupID].Characters.Add(character);
                    }
                }
            }

            return(alphabet);
        }
 public AlphabetManager(Alphabet alphabet)
 {
     this.Alphabet = alphabet;
 }