using System; using System.Collections.Generic; using System.Linq; using System.Xml; using S22.Xmpp; namespace RhinoReminds { public class ReminderListUpdateEventArgs : EventArgs { } public delegate void OnReminderListUpdateHandler(object sender, ReminderListUpdateEventArgs newReminder); public class ReminderList { private int nextId = 0; private readonly object saveLock = new object(); public SortedSet Reminders = new SortedSet(new CompareReminders()); public event OnReminderListUpdateHandler OnReminderListUpdate; public ReminderList() { } public Reminder CreateReminder(Jid inJid, DateTime time, string message) { Reminder result = new Reminder(nextId++, $"{inJid.Node}@{inJid.Domain}", time, message); Console.WriteLine($"[Rhino/ReminderList] Created reminder {result}"); while (Reminders.Contains(result)) result.TweakTime(); Reminders.Add(result); OnReminderListUpdate(this, new ReminderListUpdateEventArgs()); return result; } public Reminder GetNextReminder() { if (Reminders.Count == 0) return null; return Reminders.Min; } public Reminder GetById(int targetId) { return Reminders.First((Reminder nextReminder) => nextReminder.Id == targetId); } public void DeleteReminder(Reminder nextReminder) { if (!Reminders.Remove(nextReminder)) throw new ApplicationException($"Error: Failed to remove the reminder {nextReminder} from the list!"); OnReminderListUpdate(this, new ReminderListUpdateEventArgs()); } #region Persistence public void Save(string filename) { // Make sure that the reminder thread doesn't try to save the reminders at the exact same time // we receive a request for a new reminder lock (saveLock) { // FUTURE: We could go lockless here with some work, but it's not worth it for the teensy chance & low overhead XmlWriter xml = XmlWriter.Create( filename, new XmlWriterSettings() { Indent = true } ); xml.WriteStartDocument(); xml.WriteStartElement("ReminderList"); xml.WriteElementString("NextId", nextId.ToString()); xml.WriteStartElement("Reminders"); foreach (Reminder nextReminder in Reminders) nextReminder.WriteToXml(xml); xml.WriteEndElement(); xml.WriteEndElement(); xml.WriteEndDocument(); xml.Close(); } } public static ReminderList FromXmlFile(string filepath) { XmlDocument xml = new XmlDocument(); xml.Load(filepath); ReminderList result = new ReminderList() { nextId = int.Parse(xml.GetElementsByTagName("NextId")[0].InnerText) }; foreach (XmlNode reminderXML in xml.GetElementsByTagName("Reminders")[0].ChildNodes) { Reminder nextReminder = Reminder.FromXml(reminderXML); while (result.Reminders.Contains(nextReminder)) nextReminder.TweakTime(); result.Reminders.Add(nextReminder); } return result; } #endregion } }