<?php

// Exit if accessed directly
if (!defined('ABSPATH')) {
    exit;
}

class WPSBC_Calendar_Overview_Outputter
{

    /**
     * The arguments for the calendar overview outputter
     *
     * @access protected
     * @var    array
     *
     */
    protected $args;

    /**
     * An array with WPSBC_Calendar object
     *
     * @access protected
     * @var    array
     *
     */
    protected $calendars = array();

    /**
     * An array with calendar ids
     *
     * @access protected
     * @var    array
     *
     */
    protected $calendar_ids = array();

    /**
     * The list of legend items associated with each calendar
     *
     * @access protected
     * @var    array
     *
     */
    protected $legend_items = array();

    /**
     * The list of default legend items for each calendar
     *
     * @access protected
     * @var    WPSBC_Legend_Item
     *
     */
    protected $default_legend_items = array();

    /**
     * The list of events for each calendar for the given displayed range
     *
     * @access protected
     * @var    array
     *
     */
    protected $events = array();

    /**
     * The list of events from the linked iCal feeds
     *
     * @access protected
     * @var    array
     *
     */
    protected $ical_events = array();

    /**
     * The plugin general settings
     *
     * @access protected
     * @var    array
     *
     */
    protected $plugin_settings = array();

    /**
     * Constructor
     *
     * @param array $calendars
     * @param array $args
     *
     */
    public function __construct($calendars, $args = array())
    {

        /**
         * Set arguments
         *
         */
        $this->args = wp_parse_args($args, wpsbc_get_calendar_overview_output_default_args());

        /**
         * Set the calendars
         *
         */
        $this->calendars = $calendars;

        /**
         * Set plugin settings
         *
         */
        $this->plugin_settings = get_option('wpsbc_settings', array());

        /**
         * Set calendar ids
         *
         */
        foreach ($calendars as $calendar) {
            $this->calendar_ids[] = $calendar->get('id');

            /**
             * Refresh the iCal feeds
             *
             */
            $this->refresh_ical_feeds($calendar);
        }

        /**
         * Set legend items
         *
         */
        foreach ($calendars as $calendar) {

            $this->legend_items[$calendar->get('id')] = wpsbc_get_legend_items(array('calendar_id' => $calendar->get('id')));

        }

        /**
         * Set default legend items
         *
         */
        foreach ($this->legend_items as $calendar_id => $legend_items) {

            foreach ($legend_items as $legend_item) {

                if ($legend_item->get('is_default') != 1) {
                    continue;
                }

                $this->default_legend_items[$calendar_id] = $legend_item;

            }

        }

        /**
         * Set the calendar events
         *
         */
        foreach ($calendars as $calendar) {
            $this->events[$calendar->get('id')] = wpsbc_get_events(array('calendar_id' => $calendar->get('id'), 'date_month' => $this->args['current_month'],  'date_year' => $this->args['current_year'] ));
        }

        /**
         * Set the calendar iCal events
         *
         */
        foreach ($calendars as $calendar) {

            $this->ical_events[$calendar->get('id')] = wpsbc_get_ical_feeds_as_events($calendar->get('id'), $this->events[$calendar->get('id')]);

        }

    }

    /**
     * Constructs and returns the HTML for the entire calendar overview
     *
     * @return string
     *
     */
    public function get_display()
    {

        /**
         * Prepare needed data
         *
         */
        $year_to_show = (int) $this->args['current_year'];
        $month_to_show = (int) $this->args['current_month'];

        $calendar_html_data = 'data-ids="' . implode(',', $this->calendar_ids) . '" ';

        foreach ($this->args as $arg => $val) {
            $calendar_html_data .= 'data-' . $arg . '="' . esc_attr($val) . '" ';
        }

        /**
         * Handle output for the calendar overview
         *
         */
        $output = '<div class="wpsbc-overview-container" ' . $calendar_html_data . '>';

        /**
         * Calendar Legend Top
         *
         */
        if ($this->args['show_legend'] && $this->args['legend_position'] != 'bottom') {
            $output .= $this->get_display_legend();
        }

        $output .= '<div class="wpsbc-overview-inner">';

        /**
         * Display the navigation and date numbers
         *
         */
        $output .= $this->get_display_header_row($year_to_show, $month_to_show);

        /**
         * Display the dates abbreviation
         *
         */
        if ($this->args['show_day_abbreviation']) {
            $output .= $this->get_display_header_abbreviations_row($year_to_show, $month_to_show);
        }

        /**
         * Display the calendars month
         *
         */
        foreach ($this->calendars as $calendar) {

            $output .= $this->get_display_calendar_row($calendar, $year_to_show, $month_to_show);

        }

        $output .= '</div>'; // end of .wpsbc-overview-inner

        /**
         * Calendar Legend Top
         *
         */
        if ($this->args['show_legend'] && $this->args['legend_position'] == 'bottom') {
            $output .= $this->get_display_legend();
        }

        /**
         * Calendar Custom CSS
         *
         */
        $output .= $this->get_custom_css();

        /**
         * Flag needed for Gutenberg block to properly display the calendar
         * in the editor after the block settings are changed
         *
         */
        $output .= '<div class="wpsbc-overview-container-loaded" data-just-loaded="1"></div>';

        $output .= '</div>'; // end of .wpsbc-overview-container

        return $output;

    }

    /**
     * Constructs and returns the HTML row for the main header
     *
     * @param int $year
     * @param int $month
     *
     * @return string
     *
     */
    protected function get_display_header_row($year, $month)
    {

        $total_days = 31;
        $days_in_month = date('t', mktime(0, 0, 0, $month, 1, $year));

        $output = '<div class="wpsbc-overview-row wpsbc-overview-header">';

        /**
         * Calendar navigation
         *
         */
        $output .= '<div class="wpsbc-overview-header-navigation wpsbc-overview-row-header">';
        $output .= '<div class="wpsbc-overview-row-header-inner">' . $this->get_display_month_selector($year, $month) . '</div>';
        $output .= '</div>';

        /**
         * Header date numbers
         *
         */
        $output .= '<div class="wpsbc-overview-row-content">';

        for ($day = 1; $day <= $total_days; $day++) {

            $output .= '<div><div class="wpsbc-date wpsbc-date-day-of-week-'. date('N', mktime(0, 0, 0, $month, $day, $year)).'"><div class="wpsbc-date-inner">';

            if ($day <= $days_in_month) {
                $output .= $day;
            }

            $output .= '</div></div></div>';

        }

        $output .= '</div>'; // end of .wpsbc-overview-row-content

        $output .= '</div>';

        return $output;

    }

    /**
     * Constructs and returns the HTML row for the dates abbreviations
     *
     * @param int $year
     * @param int $month
     *
     * @return string
     *
     */
    protected function get_display_header_abbreviations_row($year, $month)
    {

        $total_days = 31;
        $days_in_month = date('t', mktime(0, 0, 0, $month, 1, $year));

        $output = '<div class="wpsbc-overview-row wpsbc-overview-row-abbreviations">';

        /**
         * Empty row header
         *
         */
        $output .= '<div class="wpsbc-calendar-header-navigation wpsbc-overview-row-header">';
        $output .= '<div class="wpsbc-overview-row-header-inner"></div>';
        $output .= '</div>';

        /**
         * Header abbreviations
         *
         */
        $output .= '<div class="wpsbc-overview-row-content">';

        for ($day = 1; $day <= $total_days; $day++) {

            $day_names = wpsbc_get_days_first_letters($this->args['language']);
            $index = date('N', mktime(0, 0, 0, $month, $day, $year)) - 1;

            $output .= '<div><div class="wpsbc-date wpsbc-date-day-of-week-'. date('N', mktime(0, 0, 0, $month, $day, $year)).'"><div class="wpsbc-date-inner"><strong>';

            if ($day <= $days_in_month) {
                $output .= $day_names[$index];
            }

            $output .= '</strong></div></div></div>';

        }

        $output .= '</div>'; // end of .wpsbc-overview-row-content

        $output .= '</div>';

        return $output;

    }

    /**
     * Constructs and returns the calendar HTML row for the given month of the given year
     *
     * @param WPSBC_Calendar $calendar
     * @param int              $year
     * @param int              $month
     *
     * @return string
     *
     */
    protected function get_display_calendar_row($calendar, $year, $month)
    {

        $total_days = 31;
        $days_in_month = date('t', mktime(0, 0, 0, $month, 1, $year));

        $output = '<div class="wpsbc-calendar wpsbc-overview-row">';

        /**
         * Calendar heading
         *
         */
        $output .= '<div class="wpsbc-calendar-header wpsbc-overview-row-header">';
        $output .= '<div class="wpsbc-calendar-header-inner wpsbc-overview-row-header-inner">';

        // Get calendar link if it is set
        $calendar_link = $this->get_calendar_link($calendar->get('id'), $this->args['language']);

        $calendar_name = apply_filters('wpsbc_calendar_overview_output_calendar_name', $calendar->get_name($this->args['language']), $calendar->get('id'), $calendar_link);

        if (!empty($calendar_link)) {
            $output .= '<a href="' . $calendar_link . '">' . $calendar_name . '</a>';
        } else {
            $output .= $calendar_name;
        }

        $output .= '</div>';
        $output .= '</div>';

        /**
         * Calendar dates
         *
         */
        $output .= '<div class="wpsbc-calendar-wrapper wpsbc-overview-row-content">';

        for ($day = 1; $day <= $total_days; $day++) {

            if ($day <= $days_in_month) {
                $output .= '<div>' . $this->get_display_day($calendar, $year, $month, $day) . '</div>';
            } else {
                $output .= '<div>' . $this->get_blank_day() . '</div>';
            }

        }

        $output .= '</div>'; // end of .wpsbc-calendar-wrapper

        $output .= '</div>'; // end of .wpsbc-calendar

        return $output;

    }

    /**
     * Constructs and returns the HTML of the calendar month selector from the header
     *
     * @param int $year
     * @param int $month
     *
     * @return string
     *
     */
    protected function get_display_month_selector($year, $month)
    {

        $output = '<div class="wpsbc-select-container">';

        /**
         * Hook to modify how many months are being displayed in the select dropdown
         * before the current given month of the year
         *
         * @param int $months_before
         * @param int $year
         * @param int $month
         *
         */
        $months_before = apply_filters('wpsbc_calendar_overview_output_month_selector_months_before', 3, $year, $month);

        /**
         * Hook to modify how many months are being displayed in the select dropdown
         * after the current given month of the year
         *
         * @param int $months_after
         * @param int $year
         * @param int $month
         *
         */
        $months_after = apply_filters('wpsbc_calendar_overview_output_month_selector_months_after', 12, $year, $month);

        /**
         * Hook to modify the maximum number of months to display before now()
         *
         * @param int $months_before_max
         * @param int $year
         * @param int $month
         *
         */
        $months_before_max = apply_filters('wpsbc_calendar_overview_output_month_selector_months_before_max', -1, $year, $month);

        /**
         * Hook to modify the maximum number of months to display after now()
         *
         * @param int $months_after_max
         * @param int $year
         * @param int $month
         *
         */
        $months_after_max = apply_filters('wpsbc_calendar_overview_output_month_selector_months_after_max', -1, $year, $month);

        /**
         * Hook to exclude months from the date selector
         *
         * @param array $months
         *
         */
        $excluded_months = apply_filters('wpsbc_calendar_overview_output_month_selector_exclude_months', array());

        /**
         * Hook to exclude past months from the date selector
         *
         * @param bool
         *
         */
        $show_past_months = apply_filters('wpsbc_calendar_overview_output_month_selector_hide_past_months', true);

        /**
         * Build the months array
         *
         */

        // The array that will contain all options data
        $select_options = array();

        // Maximum before time
        $before_max_month = date('n') + (12 * ceil($months_before_max / 12)) - $months_before_max;
        $before_max_year = $year - ceil($months_before_max / 12);
        $time_before_max = mktime(0, 0, 0, $before_max_month, 1, $before_max_year);

        // Maximum after time
        $after_max_month = (date('n') + $months_after_max - (12 * floor((date('n') + $months_after_max) / 12)));
        $after_max_year = $year + floor((date('n') + $months_after_max) / 12);
        $time_after_max = mktime(0, 0, 0, $after_max_month, 1, $after_max_year);

        /**
         * Add past months
         *
         */
        $_year = $year;
        $_month = $month;

        for ($i = 1; $i <= $months_before; $i++) {

            // Exit loop if the max number of months has been reached
            if ($months_before_max != -1 && mktime(0, 0, 0, $_month, 1, $_year) <= $time_before_max) {
                break;
            }

            $_month -= 1;

            if ($_month < 1) {
                $_month += 12;
                $_year -= 1;
            }

            if (in_array($_month, $excluded_months)) {
                $months_before++;
                continue;
            }

            if ($show_past_months === false && mktime(0, 0, 0, $_month + 1, 1, $_year) <= current_time('timestamp')) {
                break;
            }

            $select_options[] = array(
                'value' => mktime(0, 0, 0, $_month, 15, $_year),
                'option' => wpsbc_get_month_name($_month, $this->args['language']) . ' ' . $_year,
            );

        }

        $select_options = array_reverse($select_options);

        /**
         * Add given current month
         *
         */
        $select_options[] = array(
            'value' => mktime(0, 0, 0, $month, 15, $year),
            'option' => wpsbc_get_month_name($month, $this->args['language']) . ' ' . $year,
        );

        /**
         * Add future months
         *
         */
        $_year = $year;
        $_month = $month;

        for ($i = 1; $i <= $months_after; $i++) {

            if ($months_after_max != -1 && mktime(0, 0, 0, $_month, 1, $_year) >= $time_after_max) {
                break;
            }

            $_month += 1;

            if ($_month > 12) {
                $_month -= 12;
                $_year += 1;
            }

            if (in_array($_month, $excluded_months)) {
                $months_after++;
                continue;
            }

            $select_options[] = array(
                'value' => mktime(0, 0, 0, $_month, 15, $_year),
                'option' => wpsbc_get_month_name($_month, $this->args['language']) . ' ' . $_year,
            );

        }

        /**
         * Output select
         *
         */
        $output .= '<select>';

        foreach ($select_options as $select_option) {
            $output .= '<option value="' . esc_attr($select_option['value']) . '" ' . selected($select_option['value'], mktime(0, 0, 0, $month, 15, $year), false) . '>' . $select_option['option'] . '</option>';
        }

        $output .= '</select>';

        $output .= '</div>'; // end .wpsbc-select-container

        return $output;

    }

    /**
     * Constructs and returns the calendar HTML for the given day of the given month of the given year
     *
     * @param WPSBC_Calendar $calendar
     * @param int              $year
     * @param int              $month
     * @param int              $day
     * @param bool              $blank
     *
     * @return string
     *
     */
    protected function get_display_day($calendar, $year, $month, $day)
    {

        $output = '';

        /**
         * Get the event for the current day
         *
         */
        $event = $this->get_event_by_date($calendar, $year, $month, $day);

        /**
         * Get the event for the current day from the iCal feeds
         *
         */
        $ical_event = $this->get_ical_event_by_date($calendar, $year, $month, $day);

        if (!is_null($ical_event)) {
            $event = $ical_event;
        }

        /**
         * Get the legend item for the current day
         *
         */
        $legend_item = null;

        if (!is_null($event)) {

            foreach ($this->legend_items[$calendar->get('id')] as $li) {

                if ($event->get('legend_item_id') == $li->get('id')) {
                    $legend_item = $li;
                }

            }

        }

        if (is_null($legend_item)) {
            $legend_item = $this->default_legend_items[$calendar->get('id')];
        }

        // Determine if the current day is in the past
        $is_past = $this->is_date_past($year, $month, $day);

        $ical_changeover = apply_filters('wpsbc_calendar_outputter_ical_changeover', isset($this->args['is_admin'])) && $ical_event && $ical_event->get('meta') == 'ical-changeover' ? 'wpsbc-ical-changeover' : '';

        $output .= '<div class="wpsbc-date ' . $ical_changeover . '" ' . ('data-year="' . esc_attr($year) . '" data-month="' . esc_attr($month) . '" data-day="' . esc_attr($day) . '"') . '>';

        /**
         * Legend item output
         *
         */
        $legend_item_id_icon = $legend_item->get('id');
        $legend_item_type_icon = $legend_item->get('type');

        // If date is in the past
        if ($is_past) {

            if ($this->args['history'] == 2) {
                $legend_item_id_icon = $this->default_legend_items[$calendar->get('id')]->get('id');
                $legend_item_type_icon = $this->default_legend_items[$calendar->get('id')]->get('type');
            }

            if ($this->args['history'] == 3) {
                $legend_item_id_icon = 0;
                $legend_item_type_icon = 'single';
            }

        }

        $output .= wpsbc_get_legend_item_icon($legend_item_id_icon, $legend_item_type_icon);

        $output .= apply_filters('wpsbc_overview_calendar_outputter_date_number', '', $event, $year, $month, $day, $calendar->get('id'));

        /**
         * Tooltip output
         *
         */
        $output .= $this->get_display_day_tooltip($calendar, $year, $month, $day);

        $output .= '</div>';

        return $output;

    }

    /**
     * Constructs and returns the a blank day, which is appended to the end of the months that have less than 31 days.
     *
     * @return string
     *
     */
    protected function get_blank_day()
    {
        $output = '';

        $output .= '<div class="wpsbc-date">';

        $legend_item_id_icon = 'blank';
        $legend_item_type_icon = 'blank';

        $output .= wpsbc_get_legend_item_icon($legend_item_id_icon, $legend_item_type_icon);

        $output .= '</div>';

        return $output;
    }

    /**
     * Constructs and returns the Tooltip HTML for the given day of the given month of the given year
     *
     * @param int $year
     * @param int $month
     * @param int $day
     *
     * @return string
     *
     */
    protected function get_display_day_tooltip($calendar, $year, $month, $day)
    {

        // Get event for the current day
        $event = $this->get_event_by_date($calendar, $year, $month, $day);

        // Allow tooltip to be populated from the iCalendar tooltip field.
        $show_icalendar_tooltip = apply_filters('wpsbc_calendar_outputter_tooltip_source_icalendar', false);

        if ($show_icalendar_tooltip === true && is_null($event)) {
            $event = $this->get_ical_event_by_date($calendar, $year, $month, $day);
        }

        if (is_null($event)) {
            return '';
        }

        if (!in_array($this->args['show_tooltip'], array(2, 3))) {
            return '';
        }

        if ($this->is_date_past($year, $month, $day) && in_array($this->args['history'], array(2, 3))) {
            return '';
        }

        // Set tooltip value
        $tooltip = apply_filters('wpsbc_calendar_overview_outputter_tooltip', $event->get('tooltip'));

        if (empty($tooltip)) {
            return '';
        }

        // Output the actual tooltip
        $output = '<div class="wpsbc-tooltip">';
        $output .= '<strong>' . date_i18n(apply_filters('wpsbc_calendar_output_tooltip_date_format', 'd F Y', $calendar->get('id')), mktime(0, 0, 0, $month, $day, $year)) . '</strong>';
        $output .= $tooltip;
        $output .= '</div>';

        // Output the red tooltip indicator
        if ($this->args['show_tooltip'] == 3) {
            $output .= '<span class="wpsbc-tooltip-corner"><!-- --></span>';
        }

        return $output;

    }

    /**
     * Constructs and returns the HTML for the calendar's legend
     *
     * @return string
     *
     */
    protected function get_display_legend()
    {

        $output = '<div class="wpsbc-legend">';

        /**
         * Filter out elements that are identical
         *
         */
        $legend_items_data = array();
        $legend_items = array();

        foreach ($this->calendars as $calendar) {

            foreach ($this->legend_items[$calendar->get('id')] as $legend_item) {

                $legend_items_data[$legend_item->get('id')]['name'] = $legend_item->get('name');
                $legend_items_data[$legend_item->get('id')]['color'] = array_map('strtolower', $legend_item->get('color'));

            }

        }

        foreach ($legend_items_data as $legend_item_id => $legend_item_data) {

            if (!in_array($legend_item_data, $legend_items)) {
                $legend_items[$legend_item_id] = $legend_item_data;
            }

        }

        foreach ($this->calendars as $calendar) {

            foreach ($this->legend_items[$calendar->get('id')] as $legend_item) {

                if (in_array($legend_item->get('id'), array_keys($legend_items))) {
                    $legend_items[$legend_item->get('id')] = $legend_item;
                }

            }

        }

        /**
         * Concatenate the output
         *
         */
        foreach ($legend_items as $legend_item) {

            if ($legend_item->get('is_visible') == 0) {
                continue;
            }

            $output .= '<div class="wpsbc-legend-item">';
            $output .= wpsbc_get_legend_item_icon($legend_item->get('id'), $legend_item->get('type'));
            $output .= '<span class=wpsbc-legend-item-name>' . $legend_item->get_name($this->args['language']) . '</span>';
            $output .= '</div>';

        }

        $output .= '</div>';

        return $output;

    }

    /**
     * Constructs and returns the calendar's custom CSS
     *
     * @return string
     *
     */
    protected function get_custom_css()
    {

        $output = '<style type="text/css">';

        // Set the parent calendar class
        $calendar_parent_class = '.wpsbc-overview-container';

        /**
         * Legend Items CSS
         *
         */
        foreach ($this->calendars as $calendar) {

            foreach ($this->legend_items[$calendar->get('id')] as $legend_item) {

                $colors = $legend_item->get('color');

                $output .= $calendar_parent_class . ' .wpsbc-legend-item-icon-' . esc_attr($legend_item->get('id')) . ' div:first-of-type { background-color: ' . (!empty($colors[0]) ? esc_attr($colors[0]) : 'transparent') . '; }';
                $output .= $calendar_parent_class . ' .wpsbc-legend-item-icon-' . esc_attr($legend_item->get('id')) . ' div:nth-of-type(2) { background-color: ' . (!empty($colors[1]) ? esc_attr($colors[1]) : 'transparent') . '; }';

                $output .= $calendar_parent_class . ' .wpsbc-legend-item-icon-' . esc_attr($legend_item->get('id')) . ' div:first-of-type svg { fill: ' . (!empty($colors[0]) ? esc_attr($colors[0]) : 'transparent') . '; }';
                $output .= $calendar_parent_class . ' .wpsbc-legend-item-icon-' . esc_attr($legend_item->get('id')) . ' div:nth-of-type(2) svg { fill: ' . (!empty($colors[1]) ? esc_attr($colors[1]) : 'transparent') . '; }';

                if ($legend_item->get('is_default')) {
                    $output .= '.wpsbc-ical-changeover .wpsbc-legend-item-icon:after {background-color: ' . $colors[0] . ';}';
                }
            }

        }

        /**
         * Legend Item for Past Dates CSS
         *
         */
        $output .= $calendar_parent_class . ' .wpsbc-legend-item-icon-0 div:first-of-type { background-color: ' . (!empty($this->plugin_settings['booking_history_color']) ? esc_attr($this->plugin_settings['booking_history_color']) : '#e1e1e1') . '; }';

        $output .= '</style>';

        return $output;

    }

    /**
     * Passes through all stored events and searches for the event that matches the given date
     * If an event is found it is returned, else null is returned
     *
     * @param WPSBC_Calendar $calendar
     * @param int              $year
     * @param int              $month
     * @param int              $day
     *
     * @return mixed WPSBC_Event|null
     *
     */
    protected function get_event_by_date($calendar, $year, $month, $day)
    {

        foreach ($this->events[$calendar->get('id')] as $event) {

            if ($event->get('date_year') == $year && $event->get('date_month') == $month && $event->get('date_day') == $day) {
                return $event;
            }

        }

        return null;

    }

    /**
     * Passes through all stored ical events and searches for the event that matches the given date
     * If an event is found it is returned, else null is returned
     *
     * @param WPSBC_Calendar $calendar
     * @param int              $year
     * @param int              $month
     * @param int              $day
     *
     * @return mixed WPSBC_Event|null
     *
     */
    protected function get_ical_event_by_date($calendar, $year, $month, $day)
    {

        foreach ($this->ical_events[$calendar->get('id')] as $event) {

            if ($event->get('date_year') == $year && $event->get('date_month') == $month && $event->get('date_day') == $day) {
                return $event;
            }

        }

        return null;

    }

    /**
     * Determines whether the given date is in the past or not
     *
     * @param int $year
     * @param int $month
     * @param int $day
     *
     * @return bool
     *
     */
    protected function is_date_past($year, $month, $day)
    {

        $today = mktime(0, 0, 0, current_time('n'), current_time('j'), current_time('Y'));
        $date = mktime(0, 0, 0, $month, $day, $year);

        return ($today > $date);

    }

    /**
     * Refreshes the iCal feeds attached to the calendar
     *
     * @param WPSBC_Calendar $calendar
     *
     */
    protected function refresh_ical_feeds($calendar)
    {

        if (defined('DOING_AJAX') && DOING_AJAX) {
            return;
        }

        // Get iCal feeds
        $ical_feeds = wpsbc_get_calendar_meta_ical_feeds($calendar->get('id'));

        if (empty($ical_feeds)) {
            return;
        }

        $refresh_time = 0;

        // Get and set refresh time
        if (empty($this->plugin_settings['ical_refresh_times']) || $this->plugin_settings['ical_refresh_times'] == 'page_load') {

            $refresh_time = 0;

        } else {

            if ($this->plugin_settings['ical_refresh_times'] == 'hourly') {
                $refresh_time = HOUR_IN_SECONDS;
            } elseif ($this->plugin_settings['ical_refresh_times'] == 'daily') {
                $refresh_time = DAY_IN_SECONDS;
            } elseif ($this->plugin_settings['ical_refresh_times'] == 'custom') {

                if (empty($this->plugin_settings['ical_custom_refresh_time']) || $this->plugin_settings['ical_custom_refresh_time'] < 0) {
                    $refresh_time = 0;
                } else {

                    $refresh_unit = (empty($this->plugin_settings['ical_custom_refresh_time_unit']) || $this->plugin_settings['ical_custom_refresh_time_unit'] == 'minutes' ? MINUTE_IN_SECONDS : HOUR_IN_SECONDS);
                    $refresh_time = absint($this->plugin_settings['ical_custom_refresh_time']) * $refresh_unit;

                }

            }

        }

        // Fetch new feeds
        foreach ($ical_feeds as $ical_feed) {

            if (empty($ical_feed['id'])) {
                continue;
            }

            if (empty($ical_feed['url'])) {
                continue;
            }

            if ($refresh_time != 0 && strtotime($ical_feed['last_updated']) > (current_time('timestamp') - $refresh_time)) {
                continue;
            }

            $ical_contents = wp_remote_get($ical_feed['url'], array('timeout' => 30, 'user-agent' => 'Mozilla/5.0 ( Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36 Edg/135.0.0.0'));

            if (wp_remote_retrieve_response_code($ical_contents) != 200) {
                continue;
            }

            $ical_contents = wp_remote_retrieve_body($ical_contents);

            $ical_contents = trim($ical_contents);
            
            $ical_contents = apply_filters('wpsbc_ical_import_url_file_contents', $ical_contents);

            if (0 !== strpos($ical_contents, 'BEGIN:VCALENDAR') || false === strpos($ical_contents, 'END:VCALENDAR')) {
                continue;
            }

            $ical_feed['file_contents'] = $ical_contents;
            $ical_feed['last_updated'] = current_time('Y-m-d H:i:s');

            wpsbc_update_calendar_meta($calendar->get('id'), 'ical_feed_' . $ical_feed['id'], $ical_feed);

        }

    }

    /**
     * Helper function that prints the calendar overview
     *
     */
    public function display()
    {

        echo $this->get_display();

    }

    /**
     * Get the calendar link, internal or external
     *
     * @param int $calendar_id
     * @param string $language
     *
     * @return string
     *
     */
    public static function get_calendar_link($calendar_id, $language)
    {

        // Get calendar link type
        $calendar_link_type = wpsbc_get_calendar_meta($calendar_id, 'calendar_link_type', true);

        // Internal Link
        if ($calendar_link_type == 'internal') {
            if (wpsbc_get_calendar_meta($calendar_id, 'calendar_link_internal_translation_' . $language, true)) {
                $calendar_link_internal = wpsbc_get_calendar_meta($calendar_id, 'calendar_link_internal_translation_' . $language, true);
            } else {
                $calendar_link_internal = wpsbc_get_calendar_meta($calendar_id, 'calendar_link_internal', true);
            }
            if (!empty($calendar_link_internal)) {
                return get_permalink(absint($calendar_link_internal));
            }
        }

        // External Link
        if ($calendar_link_type == 'external') {
            if (wpsbc_get_calendar_meta($calendar_id, 'calendar_link_external_translation_' . $language, true)) {
                $calendar_link_external = wpsbc_get_calendar_meta($calendar_id, 'calendar_link_external_translation_' . $language, true);
            } else {
                $calendar_link_external = wpsbc_get_calendar_meta($calendar_id, 'calendar_link_external', true);
            }
            return esc_url($calendar_link_external);
        }

        return '';

    }

    /**
     * Get the calendar linked post id
     *
     * @param int $calendar_id
     * @param string $language
     *
     * @return string
     *
     */
    public static function get_calendar_link_post_id($calendar_id, $language)
    {

        // Get calendar link type
        $calendar_link_type = wpsbc_get_calendar_meta($calendar_id, 'calendar_link_type', true);

        // Internal Link
        if ($calendar_link_type == 'internal') {
            if (wpsbc_get_calendar_meta($calendar_id, 'calendar_link_internal_translation_' . $language, true)) {
                $calendar_link_internal = wpsbc_get_calendar_meta($calendar_id, 'calendar_link_internal_translation_' . $language, true);
            } else {
                $calendar_link_internal = wpsbc_get_calendar_meta($calendar_id, 'calendar_link_internal', true);
            }
            return absint($calendar_link_internal);
        }

        return false;

    }

}
