/
etc/
lib/
src/Abilities/
src/Abilities/Skills/
src/Abilities/Spells/
src/Abilities/Spells/Enums/
src/Affects/
src/ArtheaConsole/
src/ArtheaConsole/Properties/
src/ArtheaGUI/Properties/
src/Clans/Enums/
src/Commands/Communication/
src/Commands/ItemCommands/
src/Connections/
src/Connections/Colors/
src/Connections/Enums/
src/Connections/Players/
src/Connections/Players/Enums/
src/Continents/
src/Continents/Areas/
src/Continents/Areas/Characters/
src/Continents/Areas/Characters/Enums/
src/Continents/Areas/Items/
src/Continents/Areas/Items/Enums/
src/Continents/Areas/Rooms/
src/Continents/Areas/Rooms/Enums/
src/Continents/Areas/Rooms/Exits/
src/Creation/
src/Creation/Attributes/
src/Creation/Interfaces/
src/Database/
src/Database/Interfaces/
src/Environment/
src/Properties/
src/Scripts/Enums/
src/Scripts/Interfaces/
#region Arthea License

/***********************************************************************
*  Arthea MUD by R. Jennings (2007)      http://arthea.googlecode.com/ *
*  By using this code you comply with the Artistic and GPLv2 Licenses. *
***********************************************************************/

#endregion

using System;
using System.Collections.Generic;
using System.IO;
using Arthea.Continents.Areas.Characters;
using Arthea.Continents.Areas.Items;
using Arthea.Continents.Areas.Rooms;
using Arthea.Database;
using Arthea.Environment;

namespace Arthea.Continents.Areas
{
    /// <summary>
    /// Implementation of a area list.
    /// </summary>
    public class AreaList : List<Area>
    {
        #region [rgn] Methods (6)

        // [rgn] Public Methods (6)

        /// <summary>
        /// Finds the by id.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns>an area that contains the id</returns>
        public Area FindById(uint id)
        {
            return Find(delegate(Area area) { return id <= area.MaxId && id >= area.BaseId; });
        }

        /// <summary>
        /// Finds the free id range.
        /// </summary>
        /// <param name="range">The range.</param>
        /// <returns>the begining vnum and the end vnum</returns>
        public KeyValuePair<uint, uint> FindFreeIdRange(uint range)
        {
            uint id = 0;

            while (id < uint.MaxValue - range)
            {
                bool fConflict = false;

                foreach (Area area in this)
                {
                    if (area.BaseId >= id || id + range <= area.MaxId)
                    {
                        fConflict = true;
                        break;
                    }
                }

                if (!fConflict)
                {
                    return new KeyValuePair<uint, uint>(id, id + range);
                }

                id += range + 1;
            }

            throw new NoFreeIdException(range);
        }

        /// <summary>
        /// Finds the name.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <returns>an area</returns>
        public Area FindName(String name)
        {
            if (!name)
                return null;

            return Find(delegate(Area area) { return name.IsPrefixOf(area.Name); });
        }

        /// <summary>
        /// Loads this instance.
        /// </summary>
        public void Load()
        {
            Clear();

            Lists.ItemIndexes.Clear();
            Lists.Rooms.Clear();
            Lists.CharIndexes.Clear();
            Lists.Scripts.Clear();

            foreach (FileInfo fi in Persistance.GetDirectoryXmlFiles(Paths.AreaDir))
            {
                Log.Info("Loading area {0}...", fi.Name);
                Area area = Persistance.Load<Area>(fi.FullName);

                area.Attach();
                area.FileName = fi.Name;

                foreach (CharIndex ch in area.Characters.Values)
                {
                    ch.Attach();
                    ch.Area = area;
                }
                foreach (ItemIndex item in area.Items.Values)
                {
                    item.Attach();
                    item.Area = area;
                }
                foreach (Room room in area.Rooms.Values)
                {
                    room.Attach();
                    room.Area = area;
                }
            }

            if (Count == 0)
            {
                Log.Warn("No areas! Creating default one.");
                Area.CreateDefaultArea();
            }
        }

        /// <summary>
        /// Saves this instance.
        /// </summary>
        public void Save()
        {
            foreach (Area area in this)
                area.Save();
        }

        /// <summary>
        /// Saves the database.
        /// </summary>
        public void SaveDatabase()
        {
            foreach (Area area in this)
                DbHandler.Save(area);
        }

        /// <summary>
        /// Updates this instance.
        /// </summary>
        public void Update()
        {
            foreach (Area area in this)
            {
                area.Update();
            }
        }

        #endregion [rgn]
    }

    /// <summary>
    /// Implementation of a no free id exception.
    /// </summary>
    public class NoFreeIdException : Exception
    {
        #region [rgn] Constructors (2)

        /// <summary>
        /// Initializes a new instance of the <see cref="NoFreeIdException"/> class.
        /// </summary>
        /// <param name="range">The range.</param>
        public NoFreeIdException(uint range) : base(string.Format("Cannot find {0} free id numbers.", range))
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="NoFreeIdException"/> class.
        /// </summary>
        public NoFreeIdException() : base("No free id numbers left.")
        {
        }

        #endregion [rgn]
    }
}