/// <summary>
        ///     Apply the time-filter to the VFREEBUSY components.
        ///     A VFREEBUSY component overlaps a given time range if the condition for the
        ///     corresponding component state specified in the table (pg66 RFC 4791) is satisfied.
        /// </summary>
        /// <param name="component">THe VTODO</param>
        /// <param name="start">The start time of the filter</param>
        /// <param name="end">The end datetime of the filter</param>
        /// <returns>True if pass the filter, false otherwise.</returns>
        private static bool ApplyTimeFilterToVFREEBUSY(this ICalendarComponent component, DateTime start, DateTime end)
        {
            var DTSTART = component.GetComponentProperty("DTSTART") == null
                ? DateTime.MinValue
                : ((IValue <DateTime>)component.GetComponentProperty("DTSTART")).Value;
            var DTEND = component.GetComponentProperty("DTEND") == null
                ? DateTime.MaxValue
                : ((IValue <DateTime>)component.GetComponentProperty("DTEND")).Value;

            //VFREEBUSY has both the DTSTART and DTEND properties? Y
            // VFREEBUSY has the FREEBUSY property? *
            if (DTSTART != DateTime.MinValue && DTEND != DateTime.MaxValue)
            {
                return(start <= DTEND && end > DTSTART);
            }

            //VFREEBUSY has both the DTSTART and DTEND properties? N
            // VFREEBUSY has the FREEBUSY property? Y
            if (component.MultipleValuesProperties.ContainsKey("FREEBUSY"))
            {
                //take the freebusy properties
                var freeBProp = component.MultipleValuesProperties["FREEBUSY"]
                                .Select(x => ((IValue <Period>)x).Value);

                if (freeBProp.Any(period => start < period.End.Value && end > period.Start.Value))
                {
                    return(true);
                }
            }

            //VFREEBUSY has both the DTSTART and DTEND properties? N
            // VFREEBUSY has the FREEBUSY property? N
            return(false);
        }
        /// <summary>
        ///     Apply the time-filter to the VTODOs components.
        ///     A VTODO component overlaps a given time range if the condition for the
        ///     corresponding component state specified in the table (pg64 RFC 4791) is satisfied.
        /// </summary>
        /// <param name="component">The VTODO</param>
        /// <param name="start">The start time of the filter</param>
        /// <param name="end">The end datetime of the filter</param>
        /// <param name="expandedDates">The expaned dts by the RRULEs if any.</param>
        /// <returns>True if pass the filter, false otherwise.</returns>
        private static bool ApplyTimeFilterToVTODO(this ICalendarComponent component, DateTime start, DateTime end,
                                                   IEnumerable <DateTime> expandedDates)
        {
            var DURATION = component.GetComponentProperty("DURATION") == null
                ? null
                : ((IValue <DurationType>)component.GetComponentProperty("DURATION")).Value;
            var DUE = component.GetComponentProperty("DUE") == null
                ? null
                : ((IValue <Due>)component.GetComponentProperty("DUE")).Value;

            var COMPLETED = component.GetComponentProperty("COMPLETED") == null
                ? null
                : ((IValue <Completed>)component.GetComponentProperty("COMPLETED")).Value;

            var CREATED = component.GetComponentProperty("CREATED") == null
                ? null
                : ((IValue <Created>)component.GetComponentProperty("Created")).Value;


            //VTODO has the DTSTART property? Y
            if (expandedDates.Any())
            {
                foreach (var DTSTART in expandedDates)
                {
                    // VTODO has the DURATION property? Y
                    // VTODO has the DUE property? N
                    //  VTODO has the COMPLETED property? *
                    // VTODO has the CREATED property? *
                    if (DURATION != null && DUE == null)
                    {
                        var DTSTARTplusDURATION = DTSTART.AddDuration(DURATION);
                        if (start <= DTSTARTplusDURATION &&
                            (end > DTSTART || end > DTSTARTplusDURATION))
                        {
                            return(true);
                        }
                    }

                    // VTODO has the DURATION property? N
                    // VTODO has the DUE property? Y
                    //  VTODO has the COMPLETED property? *
                    // VTODO has the CREATED property? *
                    else if (DUE != null)
                    {
                        if ((start < DUE.Value || start <= DTSTART) &&
                            (end > DTSTART) || end >= DUE.Value)
                        {
                            return(true);
                        }
                    }

                    // VTODO has the DURATION property? N
                    // VTODO has the DUE property? N
                    //  VTODO has the COMPLETED property? *
                    // VTODO has the CREATED property? *
                    if (DUE == null && DURATION == null)
                    {
                        if (start <= DTSTART && end > DTSTART)
                        {
                            return(true);
                        }
                    }
                }
            }

            //VTODO has the DTSTART property? N
            else
            {
                // VTODO has the DURATION property? N
                // VTODO has the DUE property? Y
                //  VTODO has the COMPLETED property? *
                // VTODO has the CREATED property? *
                if (DUE != null && DURATION == null)
                {
                    if (start < DUE.Value && end >= DUE.Value)
                    {
                        return(true);
                    }
                }

                // VTODO has the DURATION property? N
                // VTODO has the DUE property? N
                //  VTODO has the COMPLETED property? Y
                // VTODO has the CREATED property? Y
                if (COMPLETED != null && CREATED != null)
                {
                    if ((start <= CREATED.Value || start <= COMPLETED.Value) &&
                        end >= CREATED.Value || end >= COMPLETED.Value)
                    {
                        return(true);
                    }
                }

                // VTODO has the DURATION property? N
                // VTODO has the DUE property? N
                //  VTODO has the COMPLETED property? Y
                // VTODO has the CREATED property? N
                else if (COMPLETED != null && CREATED == null)
                {
                    if (start <= COMPLETED.Value && end >= COMPLETED.Value)
                    {
                        return(true);
                    }
                }

                // VTODO has the DURATION property? N
                // VTODO has the DUE property? N
                //  VTODO has the COMPLETED property? N
                // VTODO has the CREATED property? Y
                else if (COMPLETED == null && CREATED != null)
                {
                    if (end > CREATED.Value)
                    {
                        return(true);
                    }
                }
            }
            // VTODO has the DURATION property? N
            // VTODO has the DUE property? N
            //  VTODO has the COMPLETED property? N
            // VTODO has the CREATED property? N
            return(true);
        }
        /// <summary>
        ///     Apply the time-filter to the VEVENT components.
        ///     A VEVENT component overlaps a given time range if the condition for the
        ///     corresponding component state specified in the table (pg64 RFC 4791) is satisfied.
        /// </summary>
        /// <param name="component">THe VTODO</param>
        /// <param name="start">The start time of the filter</param>
        /// <param name="end">The end datetime of the filter</param>
        /// <param name="expandedDates">The expaned dts by the RRULEs if any.</param>
        /// <returns>True if pass the filter, false otherwise.</returns>
        private static bool ApplyTimeFilterToVEVENT(this ICalendarComponent component, DateTime start, DateTime end,
                                                    IEnumerable <DateTime> expandedDates)
        {
            var compEndTimeProp = component.GetComponentProperty("DTEND");

            foreach (var DTSTART in expandedDates)
            {
                //VEVENT has the DTEND property? Y
                // VEVENT has the DURATION property? N
                // DURATION property value is greater than 0 seconds? N
                // DTSTART property is a DATE-TIME value? *
                if (compEndTimeProp != null)
                {
                    var DTEND = ((IValue <DateTime>)compEndTimeProp).Value;
                    if (start < DTEND && end > DTSTART)
                    {
                        return(true);
                    }
                }

                var durationProp = component.GetComponentProperty("DURATION");

                //VEVENT has the DTEND property? N
                // VEVENT has the DURATION property? Y
                if (durationProp != null)
                {
                    var DURATION            = ((IValue <DurationType>)durationProp).Value;
                    var DTSTARTplusDURATION = DTSTART.AddDuration(DURATION);

                    // DURATION property value is greater than 0 seconds? Y
                    // DTSTART property is a DATE-TIME value? *
                    if (DURATION.IsPositive)
                    {
                        if (start < DTSTARTplusDURATION && end > DTSTART)
                        {
                            return(true);
                        }
                    }
                    // DURATION property value is greater than 0 seconds? N
                    // DTSTART property is a DATE-TIME value? *
                    else
                    {
                        if (start <= DTSTART && end > DTSTART)
                        {
                            return(true);
                        }
                    }
                }

                //VEVENT has the DTEND property? N
                // VEVENT has the DURATION property? N
                // DURATION property value is greater than 0 seconds? N
                // DTSTART property is a DATE-TIME value? Y
                if (start <= DTSTART && end > DTSTART)
                {
                    return(true);
                }

                //VEVENT has the DTEND property? N
                // VEVENT has the DURATION property? N
                // DURATION property value is greater than 0 seconds? N
                // DTSTART property is a DATE-TIME value? N
                if (start < DTSTART.AddDays(1) && end > DTSTART)
                {
                    return(true);
                }
            }
            return(false);
        }
        /// <summary>
        ///     Apply the time filter to the given component as
        ///     defined in 9.9 CALDAV:time-range XML Element.
        /// </summary>
        /// <param name="component">The component where to apply the filter.</param>
        /// <param name="filter">The filter to apply.</param>
        /// <returns>True if the component pass the filter, false otherwise.</returns>
        private static bool ApplyTimeFilter(this ICalendarComponent component, IXMLTreeStructure filter)
        {
            DateTime?start;
            DateTime?end;

            //get the start and time attributes of the filter.
            if (filter.Attributes.ContainsKey("start"))
            {
                filter.Attributes["start"].ToDateTime(out start);
            }
            else //if not then assign infinite
            {
                start = DateTime.MinValue;
            }

            if (filter.Attributes.ContainsKey("end"))
            {
                filter.Attributes["end"].ToDateTime(out end);
            }
            else //if not then assign -infinite
            {
                end = DateTime.MaxValue;
            }

            //Get the DTSTART of the component.
            var compDTSTART = component.GetComponentProperty("DTSTART") == null
                ? DateTime.MaxValue
                : ((IValue <DateTime>)component.GetComponentProperty("DTSTART")).Value;

            //if the component contains RRULES then expand the dts
            IEnumerable <DateTime> expandedDates = null;

            if (component.MultipleValuesProperties.ContainsKey("RRULE"))
            {
                expandedDates = compDTSTART.ExpandTime(component.GetMultipleCompProperties("RRULE").Select(
                                                           x => ((IValue <Recur>)x).Value).ToList());
            }
            if (expandedDates == null)
            {
                expandedDates = new List <DateTime> {
                    compDTSTART
                }
            }
            ;

            if (component is VEvent)
            {
                return(component.ApplyTimeFilterToVEVENT(start.Value, end.Value, expandedDates));
            }
            if (component is VTodo)
            {
                return(component.ApplyTimeFilterToVTODO(start.Value, end.Value, expandedDates));
            }
            if (component is VJournal)
            {
                throw new NotImplementedException("The doesn't support the VJOURNALs yet.");
            }
            if (component is VFreebusy)
            {
                return(component.ApplyTimeFilterToVFREEBUSY(start.Value, end.Value));
            }
            if (component is VAlarm)
            {
                return(component.ApplyTimeFilterToVALARM(start.Value, end.Value));
            }
            return(false);
        }