using System;
using System.Data;
using System.Text;
using System.Threading;
using System.Collections;
using Holo.Virtual.Users;
using Ion.Storage;
namespace Holo.Managers
{
///
/// Provides management for events hosted by virtual users in their virtual rooms.
///
public static class eventManager
{
#region Declares
///
/// Array of hashtables that keeps the virtualEvent structs.
///
private static Hashtable[] Events;
///
/// The thread that removes the 'dead events' (virtual events where the hoster has left the virtual room where the event is hosted) from the manager every xx seconds. (configureable in system_config)
///
private static Thread deadEventDropper;
///
/// The amount of seconds between every 'check dead events' check. Initialized in seconds and multiplied with 1000, so value in milliseconds.
///
private static int deadEventDropInterval;
///
/// The amount of categories where virtual users can create virtual events in. Add and edit category titles in external_texts.
///
internal static int categoryAmount;
#endregion
#region Manager voids
///
/// Initializes or resets the virtual event manager, intializing the amount of categories and starting the 'dead event' collector.
///
public static void Init()
{
try { deadEventDropper.Abort(); }
catch { }
categoryAmount = int.Parse(Config.getTableEntry("events_categorycount"));
Events = new Hashtable[categoryAmount];
for (int i = 0; i < categoryAmount; i++)
Events[i] = new Hashtable();
deadEventDropInterval = int.Parse(Config.getTableEntry("events_deadevents_removeinterval")) * 1000;
deadEventDropper = new Thread(new ThreadStart(dropDeadEvents));
deadEventDropper.Priority = ThreadPriority.BelowNormal;
deadEventDropper.Start();
}
///
/// Ran on a thread with an interval of 2 minutes. Drops 'dead' virtual events (events where the hoster has left the virtual room where the event was hosted) from the manager.
///
private static void dropDeadEvents()
{
while (true)
{
for (int i = 0; i < categoryAmount; i++)
{
Hashtable EventTable = (Hashtable)Events[i].Clone();
foreach (virtualEvent Event in EventTable.Values)
{
if (userManager.containsUser(Event.userID) == false)
{
using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient())
{
dbClient.runQuery("DELETE FROM events WHERE roomid = '" + Event.roomID + "'");
}
Events[i].Remove(Event.roomID);
}
else
{
virtualUser Hoster = userManager.getUser(Event.userID);
if (Hoster._roomID != Event.roomID)
{
using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient())
{
dbClient.runQuery("DELETE FROM events WHERE roomid = '" + Event.roomID + "'");
}
Events[i].Remove(Event.roomID);
Hoster._hostsEvent = false;
}
}
}
}
Thread.Sleep(deadEventDropInterval); // Sleep the configured amount of time before repeating
Out.WriteTrace("Drop dead event loop");
}
}
#endregion
#region Event management
///
/// Creates a new virtual event with the details given in the correct category.
///
/// The ID of the category to host the event in.
/// The database ID of the virtual user that hosts the event.
/// The database ID of the virtual room where the event is hosted.
/// The name of the new virtual event.
/// The description of the new virtual event.
public static void createEvent(int categoryID, int userID, int roomID, string Name, string Description)
{
if (Events[categoryID - 1].Contains(roomID) == false)
{
virtualEvent Event = new virtualEvent(roomID, userID, Name, Description);
using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient())
{
dbClient.AddParamWithValue("ename", Name);
dbClient.AddParamWithValue("edescription", Description);
dbClient.runQuery("INSERT INTO events (name,description,userid,roomid,category,date) VALUES (@ename, @edescription, '" + userID + "', '" + roomID + "', '" + categoryID + "', '" + DateTime.Now.TimeOfDay.ToString() + "')");
}
Events[categoryID - 1].Add(roomID, Event);
}
}
///
/// Scrolls through all categories to remove a virtual event from the event manager, if the event is removed then the void is exited.
///
/// The database ID of the virtual room where the event was hosted.
public static void removeEvent(int roomID)
{
for (int i = 0; i < categoryAmount; i++)
{
if(Events[i].ContainsKey(roomID))
{
using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient())
{
dbClient.runQuery("DELETE FROM events WHERE roomid = '" + roomID + "'");
}
Events[i].Remove(roomID);
return;
}
}
}
///
/// Edits a virtual event and re-inserts it in the category.
///
/// The ID of the category where the event is hosted.
/// The database ID of the virtual room where the event was hosted.
/// The (new) name of the virtual event.
/// The (new) description of the virtual event.
public static void editEvent(int categoryID, int roomID, string Name, string Description)
{
if (Events[categoryID - 1].Contains(roomID))
{
virtualEvent Event = (virtualEvent)Events[categoryID - 1][roomID];
Event.Name = Name;
Event.Description = Description;
using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient())
{
dbClient.AddParamWithValue("name", Name);
dbClient.AddParamWithValue("desc", Description);
dbClient.runQuery("UPDATE events SET name = @name ,description = @desc ,category = '" + categoryID + "',date = '" + DateTime.Now.TimeOfDay.ToString() + "' WHERE roomid = '" + roomID + "'");
}
Events[categoryID - 1].Remove(roomID);
Events[categoryID - 1].Add(roomID,Event); // Swap (because the object is a struct)
}
}
///
/// Returns a boolean that indicates if there exists a category with the given ID.
///
/// The ID of the category to check.
public static bool categoryOK(int categoryID)
{
return (categoryID > 0 && categoryID <= categoryAmount);
}
///
/// Returns a string of all the virtual events in a certain category, where the hosting user is inside his/her virtual room. Other events will be ignored.
///
/// The category ID to get the events of.
public static string getEvents(int categoryID)
{
try
{
int Count = 0;
StringBuilder List = new StringBuilder();
Hashtable Current = (Hashtable)Events[categoryID - 1].Clone();
foreach (virtualEvent Event in Current.Values)
{
virtualUser EndUser = userManager.getUser(Event.userID);
if (EndUser != null) // Hoster is online
{
List.Append(Event.roomID + Convert.ToChar(2).ToString() + EndUser._Username + Convert.ToChar(2) + Event.Name + Convert.ToChar(2) + Event.Description + Convert.ToChar(2) + Event.Started + Convert.ToChar(2));
Count++;
}
}
Current.Clear();
return Encoding.encodeVL64(Count) + List.ToString();
}
catch { return "H"; }
}
///
/// Returns the information string about a single virtual event. If the event isn't found in a category, or the hoster isn't online, then -1 is returned.
///
/// The database ID of the virtual room.
public static string getEvent(int roomID)
{
try
{
for (int i = 0; i < categoryAmount; i++)
{
if (Events[i].ContainsKey(roomID))
{
virtualEvent Event = (virtualEvent)Events[i][roomID];
return Event.userID + Convert.ToChar(2).ToString() + userManager.getUser(Event.userID)._Username + Convert.ToChar(2).ToString() + Event.roomID + Convert.ToChar(2).ToString() + Encoding.encodeVL64(i + 1) + Event.Name + Convert.ToChar(2).ToString() + Event.Description + Convert.ToChar(2).ToString() + Event.Started + Convert.ToChar(2).ToString();
}
}
return "-1";
}
catch { return "-1"; }
}
#endregion
#region Private objects
///
/// Represents a virtual event hosted by a virtual user in his/her virtual room.
///
private struct virtualEvent
{
///
/// The database ID of the virtual room where this event takes place.
///
internal int roomID;
///
/// The database ID of the virtual user that hosts this user in his/her virtual room.
///
internal int userID;
///
/// The name of this virtual event.
///
internal string Name;
///
/// The description of this virtual event.
///
internal string Description;
///
/// The time this virtual event started. (today)
///
internal string Started;
///
/// Intializes a new virtual event.
///
/// The database ID of the virtual room where this event is hosted.
/// The database ID of the virtual user that hosts this event in his/her virtual room.
/// The name of this event.
/// The description of this event.
internal virtualEvent(int roomID, int userID, string Name, string Description)
{
this.roomID = roomID;
this.userID = userID;
this.Name = Name;
this.Description = Description;
this.Started = DateTime.Now.ToShortTimeString();
}
}
#endregion
}
}