private EKCalendar CreateEKCalendar(string calendarName, string color = null)
        {
            var calendar = EKCalendar.Create(EKEntityType.Event, _eventStore);

            calendar.Source = _eventStore.Sources.First(source => source.SourceType == EKSourceType.Local);
            calendar.Title  = calendarName;

            if (!string.IsNullOrEmpty(color))
            {
                calendar.CGColor = ColorConversion.ToCGColor(color);
            }

            NSError error = null;

            if (!_eventStore.SaveCalendar(calendar, true, out error))
            {
                // Without this, the eventStore may return the new calendar even though the save failed.
                // (this obviously also resets any other changes, but since we own the eventStore
                //  we can be pretty confident that won't be an issue)
                //
                _eventStore.Reset();

                throw new PlatformException(error.LocalizedDescription, new NSErrorException(error));
            }

            return(calendar);
        }
 /// <summary>
 /// Creates a new Calendars.Plugin.Abstractions.Calendar from an EKCalendar
 /// </summary>
 /// <param name="ekCalendar">Source EKCalendar</param>
 /// <returns>Corresponding Calendars.Plugin.Abstractions.Calendar</returns>
 public static Calendar ToCalendar(this EKCalendar ekCalendar)
 {
     return(new Calendar
     {
         Name = ekCalendar.Title,
         ExternalID = ekCalendar.CalendarIdentifier,
         CanEditCalendar = ekCalendar.AllowsContentModifications,
         CanEditEvents = ekCalendar.AllowsContentModifications,
         Color = ColorConversion.ToHexColor(ekCalendar.CGColor)
     });
 }
        /// <summary>
        /// Creates a new calendar or updates the name and color of an existing one.
        /// </summary>
        /// <param name="calendar">The calendar to create/update</param>
        /// <exception cref="System.ArgumentException">Calendar does not exist on device or is read-only</exception>
        /// <exception cref="System.UnauthorizedAccessException">Calendar access denied</exception>
        /// <exception cref="Calendars.Plugin.Abstractions.PlatformException">Unexpected platform-specific error</exception>
        public async Task AddOrUpdateCalendarAsync(Calendar calendar)
        {
            await RequestCalendarAccess().ConfigureAwait(false);

            EKCalendar deviceCalendar = null;

            if (!string.IsNullOrEmpty(calendar.ExternalID))
            {
                deviceCalendar = _eventStore.GetCalendar(calendar.ExternalID);

                if (deviceCalendar == null)
                {
                    throw new ArgumentException("Specified calendar does not exist on device", "calendar");
                }
            }

            if (deviceCalendar == null)
            {
                deviceCalendar      = CreateEKCalendar(calendar.Name, calendar.Color);
                calendar.ExternalID = deviceCalendar.CalendarIdentifier;

                // Update color in case iOS assigned one
                calendar.Color = ColorConversion.ToHexColor(deviceCalendar.CGColor);
            }
            else
            {
                deviceCalendar.Title = calendar.Name;

                if (!string.IsNullOrEmpty(calendar.Color))
                {
                    deviceCalendar.CGColor = ColorConversion.ToCGColor(calendar.Color);
                }

                NSError error = null;
                if (!_eventStore.SaveCalendar(deviceCalendar, true, out error))
                {
                    // Without this, the eventStore will continue to return the "updated"
                    // calendar even though the save failed!
                    // (this obviously also resets any other changes, but since we own the eventStore
                    //  we can be pretty confident that won't be an issue)
                    //
                    _eventStore.Reset();

                    if (error.Domain == _ekErrorDomain && error.Code == (int)EKErrorCode.CalendarIsImmutable)
                    {
                        throw new ArgumentException(error.LocalizedDescription, new NSErrorException(error));
                    }
                    else
                    {
                        throw new PlatformException(error.LocalizedDescription, new NSErrorException(error));
                    }
                }
            }
        }