/// <summary>
        /// Initialization of data holders.
        /// </summary>
        /// <param name="context"></param>
        public override void EnterEventc(ICalendarParser.EventcContext context)
        {
            m_RDates.Clear();
            m_CurrentEvent.Clear();
            m_CurrentEventDateTime = DateTime.MinValue;

            //If we have found the first event, it means we are done with the header.
            m_HasWrittenHeader = true;
        }
        /// <summary>
        /// Save the date and relevant text.
        /// </summary>
        /// <param name="context"></param>
        public override void ExitDtend(ICalendarParser.DtendContext context)
        {
            var sb = new StringBuilder();
            sb.Append(context.k_dtend().GetText());
            foreach (var dtendparam in context.dtendparam())
            {
                sb.Append(dtendparam.GetText());
            }
            sb.Append(':');
            m_CurrentDTENDPrefix = sb.ToString();

            var dateTime = ParseDateTime(context.date_time_date().GetText());
            if (m_CurrentEventDateTime == DateTime.MinValue)
            {
                m_CurrentEventDateTime = dateTime;
            }
            else
            {
                m_RDates.Add(new Tuple<DateTime, DateTime>(m_CurrentEventDateTime, dateTime));
            }
        }
 /// <summary>
 /// Save the description text.
 /// </summary>
 /// <param name="context"></param>
 public override void ExitDescription(ICalendarParser.DescriptionContext context)
 {
     m_CurrentEvent.Append(context.GetText());
 }
 /// <summary>
 /// Save the text of the VTIMEZONE entry.
 /// </summary>
 /// <param name="context"></param>
 public override void ExitTimezonec(ICalendarParser.TimezonecContext context)
 {
     if (!m_HasWrittenHeader)
         m_CalendarPreamble.Append(context.GetText());
 }
 /// <summary>
 /// Save the summary text.
 /// </summary>
 /// <param name="context"></param>
 public override void ExitSummary(ICalendarParser.SummaryContext context)
 {
     m_CurrentEvent.Append(context.GetText());
 }
 /// <summary>
 /// Save the repeating dates.
 /// </summary>
 /// <param name="context"></param>
 public override void ExitRdtval(ICalendarParser.RdtvalContext context)
 {
     var startTime = ParseDateTime(context.period().period_explicit().date_time()[0].GetText());
     var endTime = ParseDateTime(context.period().period_explicit().date_time()[1].GetText());
     m_RDates.Add(new Tuple<DateTime, DateTime>(startTime, endTime));
 }
 public override void ExitIcalstream(ICalendarParser.IcalstreamContext context)
 {
     m_SB.AppendLine("BEGIN:VCALENDAR");
     m_SB.Append(m_CalendarPreamble.ToString());
     m_Events.Sort(delegate(IcalEvent x, IcalEvent y)
     {
         return x.StartTime.CompareTo(y.StartTime);
     });
     foreach (var vevent in m_Events)
     {
         m_SB.Append(vevent.Text);
     }
     m_SB.AppendLine("END:VCALENDAR");
 }
        /// <summary>
        /// Write a copy of the entire event for each repeated date.
        /// </summary>
        /// <remarks>
        /// It seems that neither Google Calendar nor Lotus Notes handle the RDATE property properly.
        /// We need to turn all events that contain the RDATE property into several copies of the same
        /// event with different start and end times.
        /// </remarks>
        /// <param name="context"></param>
        public override void ExitEventc(ICalendarParser.EventcContext context)
        {
            var pre = string.Format("{0}:{1}",
                                    context.k_begin().GetText(),
                                    context.k_vevent()[0].GetText());

            var post = string.Format("{0}:{1}",
                                    context.k_end().GetText(),
                                    context.k_vevent()[1].GetText());

            var sb = new StringBuilder();
            foreach (var dates in m_RDates)
            {
                sb.Clear();
                sb.AppendLine(pre);
                sb.Append(m_CurrentEvent.ToString());

                sb.Append(m_CurrentDTSTARTPrefix).Append(dates.Item1.ToString(dateTimeFormat));
                sb.AppendLine();

                sb.Append(m_CurrentDTENDPrefix).Append(dates.Item2.ToString(dateTimeFormat));
                sb.AppendLine();

                sb.AppendLine(post);
                m_Events.Add(new IcalEvent()
                    {
                        StartTime = dates.Item1,
                        Text = sb.ToString()
                    });
            }
        }
        static void Main(string[] args)
        {
            var calendarContents = new StringBuilder();
            Console.WriteLine("Preprocessing calendar file...");
            int nbrIncluded = 0;
            int nbrEvents = 0;
            using (var reader = new System.IO.StreamReader(@"..\..\NotesCalendar.ics"))
            {
                while (!reader.EndOfStream)
                {
                    var line = reader.ReadLine();
                    if (line.Trim() == "BEGIN:VEVENT")
                    {
                        nbrEvents++;
                        var currentEvent = new StringBuilder();
                        bool includeEvent = false;
                        while (line.Trim() != "END:VEVENT")
                        {
                            currentEvent.AppendLine(line);
                            if (line.StartsWith("DTSTART"))
                            {
                                int dateIndex = line.IndexOf(':') + 1;
                                var startDate = DateTime.ParseExact(line.Substring(dateIndex), "yyyyMMddTHHmmss", System.Globalization.CultureInfo.InvariantCulture);
                                if (startDate >= DateTime.Now.AddDays(-7))
                                {
                                    includeEvent = true;
                                }
                            }
                            line = reader.ReadLine();
                        }
                        currentEvent.AppendLine(line);
                        if (includeEvent)
                        {
                            nbrIncluded++;
                            calendarContents.Append(currentEvent.ToString());
                        }
                    }
                    else
                    {
                        calendarContents.AppendLine(line);
                    }
                }
            }
            Console.WriteLine("Skipped {0} events. Parsing {1} events...", nbrEvents - nbrIncluded, nbrIncluded);

            var stringBuilder = new StringBuilder();
            AntlrInputStream input = new AntlrInputStream(calendarContents.ToString());
            ITokenSource lexer = new ICalendarLexer(input);
            ITokenStream tokens = new CommonTokenStream(lexer);
            ICalendarParser parser = new ICalendarParser(tokens);
            DateTime start = DateTime.Now;
            var tree = parser.parse();
            var span = DateTime.Now - start;
            ParseTreeWalker.Default.Walk(new ICalendarTrimmerListener(stringBuilder), tree);
            Console.WriteLine("Parsing finished after {0:g}.", span);

            using (var writer = new System.IO.StreamWriter(@"..\..\NotesCalendarTrimmed.ics"))
            {
                writer.WriteLine(stringBuilder.ToString());
            }

            Console.ReadKey();
        }