private void button1_Click(object sender, EventArgs e)
        {
            var str1 = "Hello";
            var str2 = "Hello";

            var hash1 = EventHasher.GetHash(str1);
            var hash2 = EventHasher.GetHash(str2);

            //var path = Environment.GetFolderPath( Environment.SpecialFolder.ApplicationData ) + "\\OutlookGoogleSync\\" + "calendarItems.xml";

            //if ( File.Exists( path ) )
            //    File.Delete( path );

            //Settings.Default.IsInitialLoad = true;
            //Settings.Default.Save();
            //MessageBox.Show( this, "Reset Initial Load", "Reset", MessageBoxButtons.OK );
        }
        public bool Equals(CalendarItem other)
        {
            if (other == null)
            {
                return(false);
            }

            var idEqual =
                EventHasher.Equals(CalendarItemIdentifier.EventHash, other.CalendarItemIdentifier.EventHash);

            if (!idEqual && !string.IsNullOrEmpty(CalendarItemIdentifier.GoogleId) &&
                !string.IsNullOrEmpty(other.CalendarItemIdentifier.GoogleId))
            {
                idEqual |= CalendarItemIdentifier.GoogleId.Equals(other.CalendarItemIdentifier.GoogleId);
            }

            if (!idEqual && !string.IsNullOrEmpty(CalendarItemIdentifier.OutlookEntryId) &&
                !string.IsNullOrEmpty(other.CalendarItemIdentifier.OutlookEntryId))
            {
                idEqual |= CalendarItemIdentifier.OutlookEntryId.Equals(other.CalendarItemIdentifier.OutlookEntryId);
            }

            return(idEqual);
        }
        public void AddAppointment(CalendarItem item)
        {
            try
            {
                // Create the new appointmentItem and move it into the correct folder. (Ensure to grab the new event after it is moved since "move"
                // will create a copy of the item in the new folder and if you just save it, Outlook will create two copies of the appointment.)
                var tempEvent = item.GetOutlookAppointment((AppointmentItem)CurrentApplication.CreateItem(OlItemType.olAppointmentItem));
                var newEvent  = tempEvent.Move(m_folder);
                newEvent.Save();

                // Update the old Identifier
                var oldId = item.CalendarItemIdentifier;
                // TODO: regenerate hash
                item.CalendarItemIdentifier = new Identifier(oldId.GoogleId, oldId.GoogleICalUId, newEvent.EntryID, newEvent.GlobalAppointmentID, EventHasher.GetHash(item));
                Archiver.Instance.UpdateIdentifier(oldId, item.CalendarItemIdentifier);

                Log.Write($"Added {item} to Outlooks Calendar {m_folder.Name}");

                Marshal.ReleaseComObject(newEvent);
                Marshal.ReleaseComObject(tempEvent);
            } catch (Exception ex)
            {
                Log.Write(ex, item);
                MessageBox.Show("Outlook Sync: The following error occurred: " + ex.Message);
            }
        }
        public void UpdateAppointment(CalendarItem ev)
        {
            try
            {
                var oldId = ev.CalendarItemIdentifier;
                Log.Write($"Updating recurring Outlook appointment, {ev.Subject}");

                if (!string.IsNullOrEmpty(ev.CalendarItemIdentifier.OutlookEntryId))
                {
                    if (CurrentApplication.Session.GetItemFromID(ev.CalendarItemIdentifier.OutlookEntryId, m_folder.Store.StoreID) is
                        AppointmentItem item)
                    {
                        if (item.RecurrenceState == OlRecurrenceState.olApptMaster)
                        {
                            AppointmentItem temp = ev.GetOutlookAppointment(
                                CurrentApplication.CreateItem(OlItemType.olAppointmentItem));
                            var newMaster = temp.Move(m_folder);

                            item.Delete();
                            newMaster.Save();

                            ev.CalendarItemIdentifier = new Identifier(oldId.GoogleId, oldId.GoogleICalUId, newMaster.EntryID, newMaster.GlobalAppointmentID, EventHasher.GetHash(ev));

                            Marshal.ReleaseComObject(temp);
                            Marshal.ReleaseComObject(newMaster);
                        }
                        else if (item.RecurrenceState == OlRecurrenceState.olApptNotRecurring)
                        {
                            ev.GetOutlookAppointment(item);
                            item.Save();

                            ev.CalendarItemIdentifier = new Identifier(oldId.GoogleId, oldId.GoogleICalUId, item.EntryID, item.GlobalAppointmentID, EventHasher.GetHash(ev));
                        }

                        Marshal.ReleaseComObject(item);
                    }
                }

                ev.Action &= ~CalendarItemAction.GeneratedId;
                ev.Action &= ~CalendarItemAction.OutlookUpdate;

                Log.Write($"Finished updating Outlook appointment, {ev.Subject}");

                Archiver.Instance.UpdateIdentifier(oldId, ev.CalendarItemIdentifier);
            } catch (Exception ex)
            {
                Log.Write(ex, ev);
            }
        }
        /// <summary>
        /// Add an appointment to the selected Google calendar.
        /// </summary>
        /// <param name="item">The CalendarItem to add</param>
        /// <returns>nothing</returns>
        public void AddAppointment(CalendarItem item)
        {
            try
            {
                PerformAuthentication();

                Event newEvent;
                if (string.IsNullOrEmpty(item.CalendarItemIdentifier.GoogleICalUId))
                {
                    newEvent = m_service.Events.Insert(item.GetGoogleCalendarEvent(), m_currentCalendar).Execute();
                }
                else
                {
                    newEvent = m_service.Events.Import(item.GetGoogleCalendarEvent(), m_currentCalendar).Execute();
                }

                Log.Write($"Added {item.Subject} Appointment to Google");

                var oldId = item.CalendarItemIdentifier;
                item.CalendarItemIdentifier = new Identifier(newEvent.Id, newEvent.ICalUID, oldId.OutlookEntryId, oldId.OutlookGlobalId, EventHasher.GetHash(item));

                Archiver.Instance.UpdateIdentifier(oldId, item.CalendarItemIdentifier);

                Retry?.Successful();
            } catch (GoogleApiException ex)
            {
                Log.Write(ex, item);
                HandleException(ex, "There was an error when trying to add an event to google. Review the log file to get more information.", item, RetryAction.Add);
            }
        }
        /// <summary>
        /// Updates an appointment using the specified CalendarItem
        /// </summary>
        /// <param name="ev">The updated appointment</param>
        public void UpdateAppointment(CalendarItem ev)
        {
            if (ev.Body != null && ev.Body.Contains(AUTOMATICALLY_CREATED))
            {
                Log.Write("Google Appointment update ignored because it was automatically generated by google.");
                return;
            }

            try
            {
                PerformAuthentication();

                Event gEvent = ev.GetGoogleCalendarEvent();
                if (gEvent.Id.StartsWith("_"))
                {
                    gEvent.Id = gEvent.Id.Remove(0, 1);
                }

                var newEvent = m_service.Events.Update(gEvent, m_currentCalendar, gEvent.Id).Execute();

                var oldId = ev.CalendarItemIdentifier;
                // TODO: regenerate hash
                ev.CalendarItemIdentifier = new Identifier(newEvent.Id, newEvent.ICalUID, oldId.OutlookEntryId, oldId.OutlookGlobalId, EventHasher.GetHash(ev));

                Archiver.Instance.UpdateIdentifier(oldId, ev.CalendarItemIdentifier);

                Log.Write($"Updated Google appointment, {ev.Subject}.");
                Retry?.Successful();
            } catch (GoogleApiException ex)
            {
                Log.Write(ex, ev);
                HandleException(ex, "There was an error when trying to update an event on google.", ev, RetryAction.Update);
            }
        }
        /// <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>
        /// 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);
        }