/**
  * Convert an event from a feed into a new Ai1ec_Event object and add it to
  * the calendar.
  *
  * @param Ai1ec_Event $event    Event object
  * @param vcalendar   $calendar Calendar object
  * @param bool        $export   States whether events are created for export
  *
  * @return void
  */
 function insert_event_in_calendar(Ai1ec_Event $event, vcalendar &$calendar, $export = false)
 {
     global $ai1ec_events_helper;
     $tz = Ai1ec_Meta::get_option('timezone_string');
     $e =& $calendar->newComponent('vevent');
     $uid = '';
     if ($event->ical_uid) {
         $uid = addcslashes($event->ical_uid, "\\;,\n");
     } else {
         $uid = sprintf($this->get_uid_format(), $event->post->ID);
     }
     $e->setProperty('uid', $this->_sanitize_value($uid));
     $e->setProperty('url', get_permalink($event->post_id));
     // =========================
     // = Summary & description =
     // =========================
     $e->setProperty('summary', $this->_sanitize_value(html_entity_decode(apply_filters('the_title', $event->post->post_title), ENT_QUOTES, 'UTF-8')));
     $content = apply_filters('the_content', $event->post->post_content);
     $content = str_replace(']]>', ']]>', $content);
     $content = html_entity_decode($content, ENT_QUOTES, 'UTF-8');
     // Prepend featured image if available.
     $size = null;
     if ($img_url = $event->get_post_thumbnail_url($size)) {
         $content = '<div class="ai1ec-event-avatar alignleft timely"><img src="' . esc_attr($img_url) . '" width="' . $size[0] . '" height="' . $size[1] . '" /></div>' . $content;
     }
     $e->setProperty('description', $this->_sanitize_value($content));
     // =====================
     // = Start & end times =
     // =====================
     $dtstartstring = '';
     $dtstart = $dtend = array();
     if ($event->allday) {
         $dtstart["VALUE"] = $dtend["VALUE"] = 'DATE';
         // For exporting all day events, don't set a timezone
         if ($tz && !$export) {
             $dtstart["TZID"] = $dtend["TZID"] = $tz;
         }
         // For exportin' all day events, only set the date not the time
         if ($export) {
             $e->setProperty('dtstart', $this->_sanitize_value(gmdate("Ymd", $ai1ec_events_helper->gmt_to_local($event->start))), $dtstart);
             $e->setProperty('dtend', $this->_sanitize_value(gmdate("Ymd", $ai1ec_events_helper->gmt_to_local($event->end))), $dtend);
         } else {
             $e->setProperty('dtstart', $this->_sanitize_value(gmdate("Ymd\\T", $ai1ec_events_helper->gmt_to_local($event->start))), $dtstart);
             $e->setProperty('dtend', $this->_sanitize_value(gmdate("Ymd\\T", $ai1ec_events_helper->gmt_to_local($event->end))), $dtend);
         }
     } else {
         if ($tz) {
             $dtstart["TZID"] = $dtend["TZID"] = $tz;
         }
         // This is used later.
         $dtstartstring = gmdate("Ymd\\THis", $ai1ec_events_helper->gmt_to_local($event->start));
         $e->setProperty('dtstart', $this->_sanitize_value($dtstartstring), $dtstart);
         $e->setProperty('dtend', $this->_sanitize_value(gmdate("Ymd\\THis", $ai1ec_events_helper->gmt_to_local($event->end))), $dtend);
     }
     // ========================
     // = Latitude & longitude =
     // ========================
     if (floatval($event->latitude) || floatval($event->longitude)) {
         $e->setProperty('geo', $event->latitude, $event->longitude);
     }
     // ===================
     // = Venue & address =
     // ===================
     if ($event->venue || $event->address) {
         $location = array($event->venue, $event->address);
         $location = array_filter($location);
         $location = implode(' @ ', $location);
         $e->setProperty('location', $this->_sanitize_value($location));
     }
     $categories = array();
     $language = get_bloginfo('language');
     foreach (wp_get_post_terms($event->post_id, 'events_categories') as $cat) {
         $categories[] = $cat->name;
     }
     $e->setProperty('categories', implode(',', $categories), array("LANGUAGE" => $language));
     $tags = array();
     foreach (wp_get_post_terms($event->post_id, 'events_tags') as $tag) {
         $tags[] = $tag->name;
     }
     if (!empty($tags)) {
         $e->setProperty('X-TAGS', implode(',', $tags), array("LANGUAGE" => $language));
     }
     // ==================
     // = Cost & tickets =
     // ==================
     if ($event->cost) {
         $e->setProperty('X-COST', $this->_sanitize_value($event->cost));
     }
     if ($event->ticket_url) {
         $e->setProperty('X-TICKETS-URL', $this->_sanitize_value($event->ticket_url));
     }
     // ====================================
     // = Contact name, phone, e-mail, URL =
     // ====================================
     $contact = array($event->contact_name, $event->contact_phone, $event->contact_email, $event->contact_url);
     $contact = array_filter($contact);
     $contact = implode('; ', $contact);
     $e->setProperty('contact', $this->_sanitize_value($contact));
     // ====================
     // = Recurrence rules =
     // ====================
     $rrule = array();
     if (!empty($event->recurrence_rules)) {
         $rules = array();
         foreach (explode(';', $event->recurrence_rules) as $v) {
             if (strpos($v, '=') === false) {
                 continue;
             }
             list($k, $v) = explode('=', $v);
             $k = strtoupper($k);
             // If $v is a comma-separated list, turn it into array for iCalcreator
             switch ($k) {
                 case 'BYSECOND':
                 case 'BYMINUTE':
                 case 'BYHOUR':
                 case 'BYDAY':
                 case 'BYMONTHDAY':
                 case 'BYYEARDAY':
                 case 'BYWEEKNO':
                 case 'BYMONTH':
                 case 'BYSETPOS':
                     $exploded = explode(',', $v);
                     break;
                 default:
                     $exploded = $v;
                     break;
             }
             // iCalcreator requires a more complex array structure for BYDAY...
             if ($k == 'BYDAY') {
                 $v = array();
                 foreach ($exploded as $day) {
                     $v[] = array('DAY' => $day);
                 }
             } else {
                 $v = $exploded;
             }
             $rrule[$k] = $v;
         }
     }
     // ===================
     // = Exception rules =
     // ===================
     $exrule = array();
     if (!empty($event->exception_rules)) {
         $rules = array();
         foreach (explode(';', $event->exception_rules) as $v) {
             if (strpos($v, '=') === false) {
                 continue;
             }
             list($k, $v) = explode('=', $v);
             $k = strtoupper($k);
             // If $v is a comma-separated list, turn it into array for iCalcreator
             switch ($k) {
                 case 'BYSECOND':
                 case 'BYMINUTE':
                 case 'BYHOUR':
                 case 'BYDAY':
                 case 'BYMONTHDAY':
                 case 'BYYEARDAY':
                 case 'BYWEEKNO':
                 case 'BYMONTH':
                 case 'BYSETPOS':
                     $exploded = explode(',', $v);
                     break;
                 default:
                     $exploded = $v;
                     break;
             }
             // iCalcreator requires a more complex array structure for BYDAY...
             if ($k == 'BYDAY') {
                 $v = array();
                 foreach ($exploded as $day) {
                     $v[] = array('DAY' => $day);
                 }
             } else {
                 $v = $exploded;
             }
             $exrule[$k] = $v;
         }
     }
     // add rrule to exported calendar
     if (!empty($rrule)) {
         $e->setProperty('rrule', $this->_sanitize_value($rrule));
     }
     // add exrule to exported calendar
     if (!empty($exrule)) {
         $e->setProperty('exrule', $this->_sanitize_value($exrule));
     }
     // ===================
     // = Exception dates =
     // ===================
     // For all day events that use a date as DTSTART, date must be supplied
     // For other other events which use DATETIME, we must use that as well
     // We must also match the exact starting time
     if (!empty($event->exception_dates)) {
         foreach (explode(',', $event->exception_dates) as $exdate) {
             if ($event->allday) {
                 // the local date will be always something like 20121122T000000Z
                 // we just need the date
                 $exdate = substr($ai1ec_events_helper->exception_dates_to_local($exdate), 0, 8);
                 $e->setProperty('exdate', array($exdate), array('VALUE' => 'DATE'));
             } else {
                 $params = array();
                 if ($tz) {
                     $params["TZID"] = $tz;
                 }
                 $exdate = $ai1ec_events_helper->exception_dates_to_local($exdate);
                 // get only the date + T
                 $exdate = substr($exdate, 0, 9);
                 // Take the time from
                 $exdate .= substr($dtstartstring, 9);
                 $e->setProperty('exdate', array($exdate), $params);
             }
         }
     }
 }