/// <summary>
        /// Fills this CalendarItem with the data from a Google Event object
        /// </summary>
        /// <param name="ev">The Google Event to use</param>
        public void LoadFromGoogleEvent(Event ev)
        {
            m_source = "Google";
            Start    = ev.Start.DateTimeRaw ?? ev.Start.Date;
            End      = ev.End.DateTimeRaw ?? ev.End.Date;
            Location = ev.Location;
            Body     = ev.Description;
            Subject  = ev.Summary;

            // Ensure time zone is properly setup.
            StartTimeZone       = ev.Start.TimeZone ?? TimeZoneConverter.WindowsToIana(TimeZoneInfo.Local.Id);
            EndTimeZone         = ev.End.TimeZone ?? TimeZoneConverter.WindowsToIana(TimeZoneInfo.Local.Id);
            StartTimeInTimeZone = Start;
            EndTimeInTimeZone   = End;

            var id = Archiver.Instance.FindIdentifier(ev.Id);

            if (id == null)
            {
                CalendarItemIdentifier.GoogleId = ev.Id;
            }
            else
            {
                CalendarItemIdentifier = id;
            }

            if (string.IsNullOrEmpty(CalendarItemIdentifier.GoogleICalUId))
            {
                CalendarItemIdentifier.GoogleICalUId = ev.ICalUID;
            }

            IsAllDayEvent = (ev.Start.DateTimeRaw == null && ev.End.DateTimeRaw == null);

            if (ev.Reminders.Overrides != null)
            {
                EventReminder reminder = ev.Reminders.Overrides.FirstOrDefault(x => x.Method == "popup");

                ReminderTime = reminder?.Minutes ?? DEFAULT_REMINDER_TIME;
            }
            else
            {
                m_isUsingDefaultReminders = true;
                ReminderTime = DEFAULT_REMINDER_TIME;
            }

            if (ev.Recurrence != null)
            {
                Recurrence = new Recurrence(ev.Recurrence[0], this);
            }

            if (ev.Attendees != null)
            {
                foreach (var eventAttendee in ev.Attendees)
                {
                    if (string.IsNullOrEmpty(eventAttendee.DisplayName) || string.IsNullOrEmpty(eventAttendee.Email))
                    {
                        continue;
                    }

                    Attendees.Add(new Attendee
                    {
                        Name     = eventAttendee.DisplayName ?? "",
                        Email    = eventAttendee.Email ?? "",
                        Required = !(eventAttendee.Optional ?? true)
                    });
                }
            }

            CalendarItemIdentifier.EventHash = EventHasher.GetHash(this);
        }
        /// <summary>
        /// Fills this CalendarItem with the data from an Outlook AppointmentItem object
        /// </summary>
        /// <param name="item">The Outlook AppointmentItem to use</param>
        /// <param name="createID">Specify if you need to create and ID.</param>
        public void LoadFromOutlookAppointment(AppointmentItem item, bool createID = true)
        {
            m_source = "Outlook";

            Start    = item.Start.ToString(DateTimeFormatString);
            End      = item.End.ToString(DateTimeFormatString);
            Body     = item.Body;
            Subject  = item.Subject;
            Location = item.Location;
            m_isUsingDefaultReminders = !item.ReminderSet;
            ReminderTime        = m_isUsingDefaultReminders ? DEFAULT_REMINDER_TIME : item.ReminderMinutesBeforeStart;
            StartTimeZone       = TimeZoneConverter.WindowsToIana(item.StartTimeZone.ID);
            EndTimeZone         = TimeZoneConverter.WindowsToIana(item.EndTimeZone.ID);
            IsAllDayEvent       = item.AllDayEvent;
            StartTimeInTimeZone = item.StartInStartTimeZone.ToString(DateTimeFormatString);
            EndTimeInTimeZone   = item.EndInEndTimeZone.ToString(DateTimeFormatString);

            string entryId   = null;
            string globalId  = null;
            bool   useParent = false;

            // This ensures that if we grab a occurence of a recurring appointment we use the proper global ID.
            // You must use the MasterAppointment's global ID since that is what I track.
            if (item.IsRecurring)
            {
                if (item.RecurrenceState != OlRecurrenceState.olApptMaster)
                {
                    if (item.Parent is AppointmentItem parent)
                    {
                        entryId   = parent.EntryID;
                        globalId  = parent.GlobalAppointmentID;
                        useParent = true;
                    }
                }
            }

            // Outlook is f*****g stupid and changes the GlobalAppointmentID everytime it restarts but doesn't change the EntryID so use one or the other.
            var id = Archiver.Instance.FindIdentifier(useParent ? entryId : item.EntryID) ?? Archiver.Instance.FindIdentifier(useParent ? globalId : item.GlobalAppointmentID);

            if (id == null)
            {
                CalendarItemIdentifier.OutlookEntryId  = useParent ? entryId : item.EntryID;
                CalendarItemIdentifier.OutlookGlobalId = useParent ? globalId : item.GlobalAppointmentID;
            }
            else
            {
                CalendarItemIdentifier = id;
            }

            if (string.IsNullOrEmpty(CalendarItemIdentifier.GoogleId))
            {
                if (createID)
                {
                    CalendarItemIdentifier.GoogleId = GuidCreator.Create();
                }
            }

            // Check if the event is recurring
            if (item.IsRecurring)
            {
                var recure = item.GetRecurrencePattern();
                Recurrence = new Recurrence(recure);
                //Recurrence.AdjustRecurrenceOutlookPattern( item.Start, item.End );
            }

            // Add attendees
            if (!string.IsNullOrEmpty(item.OptionalAttendees))
            {
                if (item.OptionalAttendees.Contains(";"))
                {
                    var attendees = item.OptionalAttendees.Split(';');
                    foreach (var attendee in attendees)
                    {
                        ContactItem contact = ContactItem.GetContactItem(attendee);
                        Attendees.Add(contact != null
                            ? new Attendee(contact.Name, contact.Email, false)
                            : new Attendee(attendee, false));
                    }
                }
                else
                {
                    ContactItem contact = ContactItem.GetContactItem(item.OptionalAttendees);
                    Attendees.Add(contact != null
                        ? new Attendee(contact.Name, contact.Email, true)
                        : new Attendee(item.OptionalAttendees, true));
                }
            }

            // Grab the required attendees.
            if (!string.IsNullOrEmpty(item.RequiredAttendees))
            {
                if (item.RequiredAttendees.Contains(";"))
                {
                    var attendees = item.RequiredAttendees.Split(';');
                    foreach (var attendee in attendees)
                    {
                        ContactItem contact = ContactItem.GetContactItem(attendee);
                        Attendees.Add(contact != null
                            ? new Attendee(contact.Name, contact.Email, true)
                            : new Attendee(attendee, true));
                    }
                }
                else
                {
                    ContactItem contact = ContactItem.GetContactItem(item.RequiredAttendees);
                    Attendees.Add(contact != null
                        ? new Attendee(contact.Name, contact.Email, true)
                        : new Attendee(item.RequiredAttendees, true));
                }
            }

            CalendarItemIdentifier.EventHash = EventHasher.GetHash(this);
        }
        /// <summary>
        /// Gets the Outlook AppointmentItem representation of this CalendarItem
        /// </summary>
        /// <param name="item">The AppointmentItem to edit</param>
        /// <returns>An Outlook AppointmentItem representation of this CalendarItem</returns>
        public AppointmentItem GetOutlookAppointment(AppointmentItem item)
        {
            try
            {
                item.Start       = DateTime.Parse(Start);
                item.End         = DateTime.Parse(End);
                item.Location    = Location;
                item.Body        = Body;
                item.Subject     = Subject;
                item.AllDayEvent = IsAllDayEvent;

                Microsoft.Office.Interop.Outlook.TimeZone startTz = OutlookSync.Syncer.CurrentApplication.TimeZones[TimeZoneConverter.IanaToWindows(StartTimeZone)];
                Microsoft.Office.Interop.Outlook.TimeZone endTz   = OutlookSync.Syncer.CurrentApplication.TimeZones[TimeZoneConverter.IanaToWindows(EndTimeZone)];

                item.StartTimeZone = startTz;
                item.EndTimeZone   = endTz;

                if (!m_isUsingDefaultReminders)
                {
                    item.ReminderMinutesBeforeStart = ReminderTime;
                    item.ReminderSet = true;
                }

                if (Recurrence != null)
                {
                    var pattern = item.GetRecurrencePattern();
                    Recurrence.GetOutlookPattern(ref pattern, IsAllDayEvent);
                }

                foreach (var attendee in Attendees)
                {
                    var  recipt = item.Recipients.Add(attendee.Name);
                    bool result = recipt.Resolve();

                    if (!result)
                    {
                        ContactItem contact = new ContactItem(attendee.Name, attendee.Email);
                        result = contact.CreateContact();
                    }

                    result &= recipt.Resolve();
                    if (result)
                    {
                        recipt.AddressEntry.Address = attendee.Email;
                        recipt.Type = attendee.Required
                            ? (int)OlMeetingRecipientType.olRequired
                            : (int)OlMeetingRecipientType.olOptional;
                    }
                }

                return(item);
            } catch (COMException ex)
            {
                Log.Write(ex);
                MessageBox.Show(
                    "CalendarItem: There has been an error when trying to create a outlook appointment item from a CalendarItem.", "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            return(null);
        }