<?php

namespace Eventman;


use DateTime;
use Eventman\Includes\Post\PostTypes;
use Exception;
use WP_Error;
use WP_Post;
use WP_Query;
use WP_Site;
use WP_Term;
use function get_current_screen;

/**
 * The public-facing functionality of the plugin.
 *
 * @link       http://example.com
 * @since      1.0.0
 *
 * @package    MS_Eventman
 * @subpackage MS_Eventman/public
 */

/**
 * The public-facing functionality of the plugin.
 *
 * Defines the plugin name, version, and two examples hooks for how to
 * enqueue the public-facing stylesheet and JavaScript.
 *
 * @package    MS_Eventman
 * @subpackage MS_Eventman/public
 * @author     Your Name <email@example.com>
 */
class MsEventmanPublic
{

    /**
     * The ID of this plugin.
     *
     * @since    1.0.0
     * @access   private
     * @var      string $ms_eventman The ID of this plugin.
     */
    private $ms_eventman;

    /**
     * The version of this plugin.
     *
     * @since    1.0.0
     * @access   private
     * @var      string $version The current version of this plugin.
     */
    private $version;
    /**
     * @var PostTypes
     */
    private $posts;

    /**
     * Initialize the class and set its properties.
     *
     * @param string $ms_eventman The name of the plugin.
     * @param string $version The version of this plugin.
     * @since    1.0.0
     */
    public function __construct($ms_eventman, $version)
    {
        $this->ms_eventman = $ms_eventman;
        $this->version = $version;
    }

    /**
     * Register the stylesheets for the public-facing side of the site.
     *
     * @since    1.0.0
     */
    public function enqueueStyles()
    {

        /**
         * This function is provided for demonstration purposes only.
         *
         * An instance of this class should be passed to the run() function
         * defined in MsEventmanLoader as all of the hooks are defined
         * in that particular class.
         *
         * The MsEventmanLoader will then create the relationship
         * between the defined hooks and the functions defined in this
         * class.
         */

        wp_enqueue_style('slick', plugin_dir_url(__FILE__) . 'css/slick.css', array(), $this->version, 'all');
        wp_enqueue_style('featherlight', plugin_dir_url(__FILE__) . 'css/featherlight.min.css', array(), $this->version, 'all');
        wp_enqueue_style('featherlight-gallery', plugin_dir_url(__FILE__) . 'css/featherlight.gallery.min.css', array(), $this->version, 'all');
    }

    /**
     * Register the JavaScript for the public-facing side of the site.
     *
     * @since    1.0.0
     */
    public function enqueueScripts()
    {

        /**
         * This function is provided for demonstration purposes only.
         *
         * An instance of this class should be passed to the run() function
         * defined in MsEventmanLoader as all of the hooks are defined
         * in that particular class.
         *
         * The MsEventmanLoader will then create the relationship
         * between the defined hooks and the functions defined in this
         * class.
         */


        wp_enqueue_script('slick', plugin_dir_url(__FILE__) . 'js/slick.js', ['jquery'], '1.8.0');
        wp_enqueue_script('webticker', plugin_dir_url(__FILE__) . 'js/jquery.webticker.js', ['jquery'], '3.0.0', true);
        wp_enqueue_script('featherlight', plugin_dir_url(__FILE__) . 'js/featherlight.min.js', array(), $this->version, true);
        wp_enqueue_script('featherlight-gallery', plugin_dir_url(__FILE__) . 'js/featherlight.gallery.min.js', array(), $this->version, true);
        wp_enqueue_script($this->ms_eventman, plugin_dir_url(__FILE__) . 'js/ms-eventman-public.js', ['jquery', 'slick', 'webticker'], $this->version, true);
    }

    /**
     * Add 'bloginfo', 'eventinfo', 'partner_carousel' and google, ms, and ics calendar feeds.
     */
    public function addShortcodes()
    {
        $this->addBlogInfoShortcode();
        $this->addEventInfoShortcode();
        $this->addPartnerCarouselShortcode();
        $this->addCalendarShortcodes();
        $this->replaceSocialShareShortcode();
    }

    /**
     *
     * @param $posts WP_Post[]
     * @return string
     */
    private function partnerCarousel($posts, $opts, $repeat = 1)
    {
        if (empty($posts)) {
            return '';
        }

        $data = '';
        $imagePadding = '';

        if (!empty($opts) && isset($opts['padding'])) {
            $imagePadding = 'style="padding:0 ' . str_replace('px', '', $opts['padding']) . 'px;"';
        }

        $out = '<div class="partners-glide"><div class="img_slides" ' . $data . '>';
        $outPosts = '';
        foreach ($posts as $post) {
            if (has_post_thumbnail($post)) {
                $postThumbnailId = get_post_thumbnail_id($post);

                $params = [];

                $srcset = wp_get_attachment_image_srcset($postThumbnailId);
                $sizes = wp_get_attachment_image_sizes($postThumbnailId);
                if ($srcset) {
                    $params['srcset'] = $srcset;
                    if ($sizes) {
                        $params['sizes'] = $sizes;
                    }
                }


                $outPosts .= sprintf('<span class="img_slide" ' . $imagePadding . "><a href=\"%s\"><img src=\"%s\" ",
                    get_permalink($post),
                    wp_get_attachment_image_src($postThumbnailId)[0]);
                foreach ($params as $key => $value) {
                    $outPosts .= " $key=\"$value\" ";
                }
                $outPosts .= '/></a></span>';
            }
        }
        $out .= str_repeat($outPosts, $repeat) . '</div></div>';
        return $out;
    }

    /**
     * Autogenerate menu items for other sites in the network and event years.
     * @param $items
     * @param $args
     * @return array
     */
    public function addSitesMenuOptions($items, $args)
    {
        // dont autogenerate when in admin panel
        $topNav = get_term(get_nav_menu_locations()['top-navigation'], 'nav_menu')->term_id;
        $isTopNav = $topNav === $args->term_id;
        if (!$isTopNav || is_customize_preview() || (is_admin() && function_exists('get_current_screen') && get_current_screen() && get_current_screen()->in_admin())) {
            return $items;
        }

        $out = [];
        // get the max order number
        if (sizeof($items) !== 0) {
            $orderNum = max(array_map(function ($o) {
                return $o->menu_order;
            }, $items));

            // autogenerate menu items
            foreach ($items as $item) {
                $id = $item->ID;
                if (strcasecmp($item->title, _x('Andere Beurzen', 'ms-eventman')) == 0) {
                    foreach (get_sites(['deleted' => 0, 'site__not_in' => [get_main_site_id(), get_current_blog_id()], 'public' => 1]) as $site) {
                        /** @var WP_Site $site */
                        // dont generate items for the main or current site
                        array_push($out, (object)[
                            'title' => $site->blogname,
                            'url' => $site->siteurl,
                            'menu_item_parent' => $id,
                            'menu_order' => ++$orderNum,
                            'type_label' => "Automatically Generated",
                            'type' => 'custom',
                            'classes' => 'network-site',
                            'object' => 'custom',
                            'object_id' => null,
                            'db_id' => null,
                            'ID' => null,
                            'target' => null,
                            'xfn' => null,
                            'anchor' => null,
                            'nolink' => null,
                            'hide' => null,
                            'icon' => null,
                            'sidebar' => null
                        ]);
                    }
                } elseif (strcasecmp($item->title, _x("Exhibitors", 'ms-eventman')) === 0
                    || strcasecmp($item->title, _x("Exposanten", 'ms-eventman')) === 0
                    || strcasecmp($item->title, _x("Partners", 'ms-eventman')) === 0) {
                    // generate events
                    $terms = get_terms(['taxonomy' => 'events', 'hide_empty' => false]);
                    foreach ($terms as $term) {
                        $meta = get_term_meta($term->term_id);
                        if ((isset($meta['publish']) && ($meta['publish'][0] !== 'on' || !$meta['publish'][0])) || !isset($meta['publish'])) {
                            // do not generate non-published terms
                            continue;
                        }


                        $url = get_term_link($term);
                        $lang = '';
                        if (strpos($url, '?lang=') !== false) {
                            $lang = substr($url, strpos($url, '?lang='));
                            $url = substr($url, 0, strpos($url, '?lang=') - 1) . '/';
                        }
                        $url .= (strcasecmp($item->title, _x("Exhibitors", 'ms-eventman') === 0
                                || strcasecmp($item->title, _x("Exposanten", 'ms-eventman')) === 0)
                                ?
                                'exhibitors' : 'partners') . $lang;

                        array_push($out, (object)[
                            'title' => $term->name,
                            'url' => $url,
                            'menu_item_parent' => $id,
                            'menu_order' => ++$orderNum,
                            'type_label' => "Automatically Generated",
                            'type' => 'event',
                            'object' => 'event',
                            'object_id' => $term->term_id,
                            'classes' => 'event-item',
                            'db_id' => $term->term_id,
                            'ID' => null,
                            'target' => null,
                            'xfn' => null,
                            'anchor' => null,
                            'nolink' => null,
                            'hide' => null,
                            'icon' => null,
                            'sidebar' => null
                        ]);
                    }

                    // sort high to low
                    rsort($out);
                }
            }
        }

        $out = array_merge($items, $out);
        return $out;
    }

    /**
     * Fix %events% permalinks.
     * @param $postLink
     * @param $post
     * @return string|string[]
     */
    public function permalinks($postLink, $post)
    {
        if (false !== strpos($postLink, '%events%')) {
            $eventTerm = get_the_terms($post->ID, 'events');
            if (!empty($eventTerm)) {
                $postLink = str_replace('%events%', array_pop($eventTerm)->slug, $postLink);
            } else {
                $postLink = str_replace('%events%', __('uncategorized', 'ms-eventman'), $postLink);
            }
        }
        return $postLink;
    }

    /**
     * Add rewrites for events permalinks.
     *
     * @param $rules
     * @return array
     */
    public function addRewritesForEvents($rules)
    {
        $newRules['^events/(.+)/(exhibitor|partner)s/?$'] = 'index.php?taxonomy=events&term=$matches[1]&post_type=$matches[2]s';
        $newRules['^events/(.+)/(exhibitor|partner)s/page/([0-9]+)/?$'] = 'index.php?taxonomy=events&term=$matches[1]&post_type=$matches[2]s&paged=$matches[3]';
        $newRules['^events/(.+)/page/([0-9]+)/?$'] = 'index.php?taxonomy=events&term=$matches[1]&post_type=exhibitors&paged=$matches[2]';
        $newRules['^events/(.+)/?$'] = 'index.php?taxonomy=events&term=$matches[1]&post_type=exhibitors';


        return array_merge($newRules, $rules);
    }

    /**
     * Order posts by ascending for 'get_post'.
     * @param WP_Query $query
     */
    public function orderCustomPostTypesByTitleAsc(WP_Query $query)
    {
        // only order by name in public pages
        if (is_post_type_archive(['partners', 'exhibitors']) && !is_admin()) {
            $query->set('orderby', ['title' => 'ASC']);
        }
    }

    /**
     * Limit exhibitors overview amount to 9 and partners to 12.
     * @param WP_Query $query
     * @return WP_Query
     */
    public function limitCptArchivePosts(WP_Query $query)
    {
        if (!is_admin() && $query->is_main_query()) {
            if ($query->is_post_type_archive('partners')) {
                $query->set('posts_per_page', '12');
            } elseif ($query->is_post_type_archive('exhibitors')) {
                $query->set('posts_per_page', '9');
            }
        }
        return $query;
    }

    /**
     * Set query variables for archive pages of exhibitors and partners.
     *
     * @param WP_Query $query
     * @return WP_Query
     */
    public function setQueryVarsForArchivePages(WP_Query $query)
    {
        if ($query->get('post_type') === 'nav_menu_item') {
            $query->set('tax_query', '');
            return $query;
        }

        global $post;
        $vars = $query->query_vars;
        if (isset($vars['post_type'])) {
            if (is_page() && !in_array($vars['post_type'], ['exhibitors', 'partners'])) {
                $exhibitorsPageId = get_option('exhibitors_archive_page');
                $partnersPageId = get_option('partners_archive_page');
                $isPostPageType = 'page' == get_post_type($post->ID);
                if ($isPostPageType) {
                    if ($post->ID == $exhibitorsPageId && $exhibitorsPageId != '0') {
                        $query->set('post_type', 'exhibitors');
                    } elseif ($post->ID == $partnersPageId && $partnersPageId != '0') {
                        $query->set('post_type', 'partners');
                    }
                }
            }
        }
        return $query;
    }

    /**
     * Overwrite titles for exhibitors and partners overview pages.
     * @param $title
     * @return mixed|string
     */
    public function overwriteCptArchiveTitle($title)
    {
        global $wp_query;

        if (in_array($wp_query->get('post_type'), ['exhibitors', 'partners'])) {
            $title = '';
            if ($wp_query->get('post_type') == 'exhibitors') {

                $exTitle = get_term_meta($wp_query->get_queried_object_id(), 'exhibitor_overview_title', true);
                if (!empty($exTitle)) {
                    return $exTitle;
                }

                $title .= __("Exhibitors", 'ms-eventman');
            } elseif ($wp_query->get('post_type') == 'partners') {
                $exTitle = get_term_meta($wp_query->get_queried_object_id(), 'partner_overview_title', true);
                if (!empty($exTitle)) {
                    return $exTitle;
                }

                $title .= __("Partners", 'ms-eventman');
            }

            if ($wp_query->is_tax) {
                $title .= ' ' . $wp_query->get_queried_object()->name;
            }
        }

        return $title;
    }

    /**
     * Convert RGB from hexadecimal string.
     * @return array|int
     */
    protected function getRgbFromHex(string $hex)
    {
        return sscanf($hex, "#%02x%02x%02x");
    }

    protected function addBlogInfoShortcode(): void
    {
        add_shortcode('bloginfo', function ($atts) {

            $atts = shortcode_atts(array('filter' => '', 'info' => ''), $atts, 'bloginfo');

            $infos = array(
                'name', 'description',
                'wpurl', 'url', 'pingback_url',
                'admin_email', 'charset', 'version', 'html_type', 'language',
                'atom_url', 'rdf_url', 'rss_url', 'rss2_url',
                'comments_atom_url', 'comments_rss2_url',
            );

            $filter = in_array(strtolower($atts['filter']), array('raw', 'display'), true)
                ? strtolower($atts['filter'])
                : 'display';

            return in_array($atts['info'], $infos, true) ? get_bloginfo($atts['info'], $filter) : '';
        });
    }

    protected function addEventInfoShortcode(): void
    {
        add_shortcode('event_info', function ($atts) {
            $atts = shortcode_atts(array('year' => '', 'filter' => '', 'info' => ''), $atts, 'event_info');

            $infos = array(
                'name', 'description', 'dates', 'location', 'partner_carousel'
            );

            if (empty($atts['year']) || empty($atts['info'])) {
                return '';
            }

            $filter = in_array(strtolower($atts['filter']), array('raw', 'display'), true)
                ? strtolower($atts['filter'])
                : 'display';


            $term_id = -1;
            if ($atts['year'] !== 'latest') {
                $term_id = get_term_by(
                    'slug',
                    $atts['year'],
                    'events')->term_id;
            } else {
                $terms = get_terms(
                    [
                        'taxonomy' => 'events',
                        'hide_empty' => false,
                        'order_by' => 'slug',
                        'order' => 'DESC',
                        'meta_key' => 'publish',
                        'meta_value' => 'on'
                    ]);
                $term_id = $terms[0]->term_id;
            }
            if ($term_id == -1) {
                return '';
            }

            if (in_array($atts['info'], $infos, true)) {
                if ($atts['info'] == 'dates') {
                    try {
                        $datesFrom = get_term_meta($term_id, 'date_from')[0];
                        if (!is_array($datesFrom)) {
                            $datesFrom = [$datesFrom];
                        }
                        $meta['date_from'] = new DateTime(min($datesFrom));

                        $datesTill = get_term_meta($term_id, 'date_till')[0];
                        if (!is_array($datesTill)) {
                            $datesTill = [$datesTill];
                        }
                        $meta['date_till'] = new DateTime(max($datesTill));

                        $dayOfMonthFormat = 'jS';
                        if (ICL_LANGUAGE_CODE != 'en') {
                            $dayOfMonthFormat = 'j';
                        }

                        return $meta['date_from']->format($dayOfMonthFormat) . ' ' . __($meta['date_from']->format('F'), 'ms-eventman') . ' ' . _x("until", 'ms-eventman') . ' ' . $meta['date_till']->format($dayOfMonthFormat) . ' ' . __($meta['date_till']->format('F'), 'ms-eventman');
                    } catch (Exception $e) {
                        return '';
                    }
                } elseif ($atts['info'] == 'location') {
                    return get_term_meta($term_id, 'event_location')[0];
                } else {
                    $term = get_term($term_id, 'events', ARRAY_A, $filter);
                    if (!($term instanceof WP_Error)) {
                        return $term[$atts['info']];
                    }
                }
            }
            return '';
        });
    }

    protected function addPartnerCarouselShortcode(): void
    {
        add_shortcode('partner_carousel', function ($atts) {
            $atts = shortcode_atts(['year' => '',
                'padding' => '',
                'autoplay' => '',
                'speed' => '',
                'autoplayspeed' => '',
                'repeat' => '1'],
                $atts,
                'partner_carousel');
            $term_id = -1;
            if (!isset($atts['year'])) {
                return '';
            } elseif (!empty($atts['year']) && is_numeric($atts['year'])) {
                $term_id = get_term_by(
                    'slug',
                    $atts['year'],
                    'events')->term_id;
            } elseif ($atts['year'] === 'latest') {
                $terms = get_terms(
                    [
                        'taxonomy' => 'events',
                        'hide_empty' => false,
                        'order_by' => 'slug',
                        'order' => 'DESC',
                        'meta_key' => 'publish',
                        'meta_value' => 'on'
                    ]);
                if (!empty($terms)) {
                    $term_id = $terms[0]->term_id;
                }
            }

            if ($atts['year'] === 'all') {
                $posts = get_posts([
                    'post_type' => 'partners',
                    'post_status' => ['publish'],
                    'posts_per_page' => -1,
                    'numberposts' => -1,
                    'suppress_filters' => false
                ]);
            } else {
                if ($term_id === -1) {
                    return '';
                }
                $posts = get_posts([
                    'post_type' => 'partners',
                    'post_status' => ['publish'],
                    'posts_per_page' => -1,
                    'numberposts' => -1,
                    'suppress_filters' => false,
                    'tax_query' => [
                        [
                            'taxonomy' => 'events',
                            'field' => 'term_id',
                            'terms' => $term_id,
                            'include_children' => false
                        ]
                    ]]);
            }
            $opts = [];
            if (!empty($atts['padding'])) {
                $opts['padding'] = $atts['padding'];
            }

            if (!empty($posts)) {
                return $this->partnerCarousel($posts, $opts, $atts['repeat'] ?? 1);
            }
            return '';
        });
    }

    protected function addCalendarShortcodes(): void
    {
        add_shortcode('calendar', function ($atts) {
            return get_feed_link('calendar');
        });
        add_shortcode('gcalendar', function ($atts) {
            return get_feed_link('gcalendar');
        });
        add_shortcode('mscalendar', function ($atts) {
            return get_feed_link('mscalendar');
        });
    }

    private function eventSummary(WP_Term $term)
    {
        $out = '<div id="latest-term" class="event-container">
                    <div class="col-right">';
        $out .= '</div>';
        $out .= '</div>';


        return $out;
    }

    public function addCalendarFeeds()
    {
        add_feed('calendar', [$this, 'getLatestEventIcs']);
        add_feed('gcalendar', [$this, 'getGoogleCalendarUrl']);
        add_feed('mscalendar', [$this, 'getOutlookAppointmentUrl']);
    }

    public function getLatestEventIcs()
    {
        // there must be an event
        $terms = get_terms('events');
        if (empty($terms)) {
            exit;   // terminate if no event available
        }

        // filter by published
        $publishedTerms = array_filter($terms, function (WP_Term $term) {
            return get_term_meta($term->term_id, 'publish', true) === 'on';
        });
        if (empty($publishedTerms)) {
            exit;   // terminate if no event available
        }

        // Sort by slug (must be a number)
        usort($publishedTerms, function ($t0, $t1) {
            if ((int)$t0->slug == (int)$t1->slug) {
                return 0;
            } elseif ((int)$t0->slug > (int)$t1->slug) {
                return 1;
            } else {
                return -1;
            }
        });

        // get the latest published term
        $latestPublishedTerm = array_pop($publishedTerms);
        if (!$latestPublishedTerm) {
            exit;
        }

        // get the meta fields
        $meta = get_term_meta($latestPublishedTerm->term_id);
        if (!$meta || !isset($meta['date_from']) || empty($meta['date_from']) || !isset($meta['date_till']) || empty($meta['date_from'])) {
            exit;
        }

        // get the dates from and until
        $datesFrom = array_map(function ($date) {
            return unserialize($date);
        }, $meta['date_from']);
        $datesTill = array_map(function ($date) {
            return unserialize($date);
        }, $meta['date_till']);

        // prepare output

        header('Content-type: text/calendar; charset=utf-8');
        header('Content-Disposition: inline; filename="' . str_replace(' ', '-', get_bloginfo('name')) . '.ics"');

        // create the ical data
        // get the data for the ical file
        $homepage = get_site_url();
        $event_desc = get_bloginfo('name');

        // get the startdate
        $dtstart_date = $datesFrom[0][0];

        // get the enddate
        $dtend_date = $datesTill[0][0];

        $dtstart_datetime = new DateTime($dtstart_date);
        $dtend_datetime = new DateTime($dtend_date);

        // build the .ics data
        $ical_data =
            'BEGIN:VCALENDAR' . "\r\n" .
            'VERSION:2.0' . "\r\n" .
            'PRODID:-//' . $homepage . '//NONSGML ProcessWire//DE' . "\r\n" .
            'CALSCALE:GREGORIAN' . "\r\n" .
            'METHOD:PUBLISH' . "\r\n" .
            'BEGIN:VEVENT' . "\r\n" .
            'SUMMARY:' . $event_desc . "\r\n" .
            'UID:' . md5(uniqid(mt_rand(), true)) . '@' . get_site_url() . "\r\n" .
            'CLASS:PUBLIC' . "\r\n" .
            'STATUS:CONFIRMED' . "\r\n" .
            'DTSTART:' . $dtstart_datetime->format('Ymd') . 'T' . $dtstart_datetime->format('His') . "\r\n" .
            'DTEND:' . $dtend_datetime->format('Ymd') . 'T' . $dtend_datetime->format('His') . "\r\n" .
            'DTSTAMP:' . date('Ymd') . 'T' . date('His') . "\r\n" .
            'URL:' . $homepage . "\r\n" .
            'END:VEVENT' . "\r\n" .
            'END:VCALENDAR';

        // output
        echo $ical_data;
        exit;
    }

    /**
     * Order post on hook 'get_adjacent_post'.
     * @param $orderBy
     * @param $post
     * @param $order
     * @return string
     */
    public function orderAdjacentPost($orderBy, $post, $order)
    {
        if (!in_array($post->post_type, ['exhibitors', 'partners'])) {
            return $orderBy;
        }
        return "ORDER BY p.post_title $order";
    }

    /**
     * Filter post on hook 'get_adjacent_post'.
     * @param $where
     * @param $in_same_term
     * @param $excluded_terms
     * @param $taxonomy
     * @param $post
     * @return string|string[]|null
     */
    public function filterAdjacentPost($where, $in_same_term, $excluded_terms, $taxonomy, $post)
    {
        if (!in_array($post->post_type, ['exhibitors', 'partners'])) {
            return $where;
        }

        // escape special chars
        $correctedTitle = esc_html($post->post_title);
        return preg_replace(
            "/(([a-z]+)\.post_date\s+?([=<>]+)\s+?\'[0-9\:\-\ ]+\')/",
            "\$2.post_title \$3 '{$correctedTitle}'",
            $where);
    }

    public function getGoogleCalendarUrl()
    {
        $terms = get_terms();
        if (empty($terms)) {
            exit;
        }

        $publishedTerms = array_filter($terms, function (WP_Term $term) {
            return get_term_meta($term->term_id, 'publish', true) === 'on';
        });
        if (empty($publishedTerms)) {
            exit;
        }

        usort($publishedTerms, function ($t0, $t1) {
            if ((int)$t0->slug == (int)$t1->slug) {
                return 0;
            } elseif ((int)$t0->slug > (int)$t1->slug) {
                return 1;
            } else {
                return -1;
            }
        });

        $latestPublishedTerm = array_pop($publishedTerms);
        if (!$latestPublishedTerm) {
            exit;
        }

        $meta = get_term_meta($latestPublishedTerm->term_id);
        if (!$meta || !isset($meta['date_from']) || empty($meta['date_from']) || !isset($meta['date_till']) || empty($meta['date_from'])) {
            exit;
        }


        $datesFrom = array_map(function ($date) {
            return unserialize($date);
        }, $meta['date_from'])[0];
        $datesTill = array_map(function ($date) {
            return unserialize($date);
        }, $meta['date_till'])[0];
        $query = [
            'action' => 'TEMPLATE',
            'text' => get_bloginfo('name'),
            'details' => get_bloginfo('description'),
        ];

        if (!empty($datesFrom)) {
            $dateMin = new DateTime(min($datesFrom));
        }
        if (!empty($datesTill)) {
            $dateMax = new DateTime(max($datesTill));
        }
        if (isset($dateMin) && isset($dateMax)) {
            $baseUrl = 'https://www.google.com/calendar/render';
            $dtFormat = 'Ymd\THis\Z';
            $dates = $dateMin->format($dtFormat) . '/' . $dateMax->format($dtFormat);

            $query['dates'] = $dates;
        }

        if (isset($meta['event_location']) && !empty($meta['event_location'])) {
            $query['location'] = $meta['event_location'][0];
        }

        $q = http_build_query($query);

        header('Location: ' . $baseUrl . '?' . $q);
        exit;
    }

    public function getOutlookAppointmentUrl()
    {
        $terms = get_terms();
        if (empty($terms)) {
            exit;
        }

        $publishedTerms = array_filter($terms, function (WP_Term $term) {
            return get_term_meta($term->term_id, 'publish', true) === 'on';
        });
        if (empty($publishedTerms)) {
            exit;
        }

        usort($publishedTerms, function ($t0, $t1) {
            if ((int)$t0->slug == (int)$t1->slug) {
                return 0;
            } elseif ((int)$t0->slug > (int)$t1->slug) {
                return 1;
            } else {
                return -1;
            }
        });

        $latestPublishedTerm = array_pop($publishedTerms);
        if (!$latestPublishedTerm) {
            exit;
        }

        $meta = get_term_meta($latestPublishedTerm->term_id);
        if (!$meta || !isset($meta['date_from']) || empty($meta['date_from']) || !isset($meta['date_till']) || empty($meta['date_from'])) {
            exit;
        }

        $datesFrom = array_map(function ($date) {
            return unserialize($date);
        }, $meta['date_from'])[0];
        $datesTill = array_map(function ($date) {
            return unserialize($date);
        }, $meta['date_till'])[0];
        $query = [
            'path' => '/calendar/action/compose',
            'rru' => 'addevent',
            'subject' => get_bloginfo('name'),
            'body' => get_bloginfo('description'),
        ];

        if (!empty($datesFrom)) {
            $dateMin = new DateTime(min($datesFrom));
        }
        if (!empty($datesTill)) {
            $dateMax = new DateTime(max($datesTill));
        }
        $baseUrl = 'https://outlook.office.com/owa/';
        if (isset($dateMin) && isset($dateMax)) {
            $dtFormat = 'Y-m-d\TH:i:s';
            $query['startdt'] = $dateMin->format($dtFormat);
            $query['enddt'] = $dateMax->format($dtFormat);
        }

        if (isset($meta['event_location']) && !empty($meta['event_location'])) {
            $query['location'] = $meta['event_location'][0];
        }

        $q = http_build_query($query);

        header('Location: ' . $baseUrl . '?' . $q);
        exit;
    }

    /**
     * This abomination is to overwrite the Qode(Elision) dynamic CSS for i.e. the new menu-bar.
     */
    public function dynamicCss()
    {
        global $qode_options_elision;

        $first = !empty($qode_options_elision['first_color']) ? $qode_options_elision['first_color'] : '#ffffff';
        $second = !empty($qode_options_elision['second_color']) ? $qode_options_elision['second_color'] : '#ffffff';
        $third = !empty($qode_options_elision['third_color']) ? $qode_options_elision['third_color'] : '#ffffff';
        $fourth = !empty($qode_options_elision['fourth_color']) ? $qode_options_elision['fourth_color'] : '#ffffff';
        $menuColor = !empty($qode_options_elision['dropdown_background_color']) ? $qode_options_elision['dropdown_background_color'] : '#ffffff';
        $menuAlpha = !empty($qode_options_elision['dropdown_background_transparency']) ? $qode_options_elision['dropdown_background_transparency'] : .8;
        $menuTextColor = !empty($qode_options_elision['menu_color']) ? $qode_options_elision['menu_color'] : '#000000';
        $menuTextHoverColor = !empty($qode_options_elision['menu_hovercolor']) ? $qode_options_elision['menu_hovercolor'] : '#ffffff';
        $buttonBg = !empty($qode_options_elision['button_backgroundcolor']) ? $qode_options_elision['button_backgroundcolor'] : $fourth;
        $buttonBgRgb = $this->getRgbFromHex($buttonBg);
        $firstRgb = $this->getRgbFromHex($first);
        $secondRgb = $this->getRgbFromHex($second);
        $menuRgb = $this->getRgbFromHex($menuColor);
        $buttonBgLightness = ($buttonBgRgb[0] * .2126 + $buttonBgRgb[0] * .7152 + $buttonBgRgb[0] * .0722) / 255;
        $buttonBgHoverLightness = ($menuRgb[0] * .2126 + $menuRgb[0] * .7152 + $menuRgb[0] * .0722) / 255;
        $buttonColCalculated = $buttonBgLightness - .5;
        $buttonTextColor = !empty($qode_options_elision['button_title_color']) ? $qode_options_elision['button_title_color'] : "hsl(0, 0%, calc($buttonColCalculated * -10000000%))";
        $buttonTextHoverColor = !empty($qode_options_elision['button_title_hovercolor']) ? $qode_options_elision['button_title_hovercolor'] : "hsl(0, 0%, calc($buttonBgHoverLightness * -10000000%))";
        $textColor = $qode_options_elision['text_color'] == '' ? 'black' : $qode_options_elision['text_color'];

        $block = get_option('overview_block_color') ? get_option('overview_block_color') : '#ededed';
        echo
        "<style>
        :root {
            --light: 80;
          /* the threshold at which colors are considered \"light.\" Range: integers from 0 to 100,
        recommended 50 - 70 */
            --threshold: 60;
            --switch: calc((var(--light) - var(--threshold)) * -100%);
        }

        .bg-first {
            background-color: $first;
        }
        .bg-second {
            background-color: $second;
        }
        .bg-third {
            background-color: $third;
        }
        .bg-fourth {
            background-color: $fourth;
        }
        .bg-menu {
            background-color: $menuColor;
        }

        header.elision-header-replacement.opened {
            background: transparent linear-gradient(0deg, rgba($firstRgb[0], $firstRgb[1], $firstRgb[2], $menuAlpha) 0%, rgba($menuRgb[0], $menuRgb[1], $menuRgb[2], $menuAlpha) 50%, rgba($menuRgb[0], $menuRgb[1], $menuRgb[2], $menuAlpha) 100%);
                    background-size: 400% 400%;
                background-position-y: 50%;
}
        header.elision-header-replacement {
            background:  linear-gradient(0deg, rgba($firstRgb[0], $firstRgb[1], $firstRgb[2], $menuAlpha) 0%, rgba($menuRgb[0], $menuRgb[1], $menuRgb[2], $menuAlpha) 50%, rgba($menuRgb[0], $menuRgb[1], $menuRgb[2], $menuAlpha) 100%); 
            background-size: 400% 400%;
        }
        header.elision-header-replacement a {
            color: $menuTextColor;
        }
        
        @keyframes change-bg-open {
            0% {
                background-position-y: 0;
            }
            50% {
                background-position-y: 100%;
            }
            
            100% {
                background-position-y: 100%;
            }
        }
        
        @keyframes change-bg-close {
            0% {
            background-position-y: 100%;
            }
            50% {
            background-position-y: 100%;
            }
            
            100% {
            background-position-y: 0;
            }
        }
        
        .blog_holder.masonry article .post_text {
            background-color: $block;
        }
        
        header.elision-header-replacement.solid:not(.opened) {
            background: $first;
            transition: background .5s ease-in-out;
        }
        
        .elision-header-replacement ul > li:not(.top-left-navigation-item):hover > a {
            color: $menuTextHoverColor;
        }
        
        .menu-top-menu-container > ul > li.button {
            background: $buttonBg;
        }
        
        .menu-top-menu-container > ul > li.button:hover {
            background: transparent;
        }
        .menu-top-menu-container > ul > li.button:hover > a {
            color: $buttonTextHoverColor;
        }
            
        .menu-top-menu-container > ul > li.button > a {
            color: $buttonTextColor;
            font-weight: 600;
        }
        </style>";

        $scrollAmount = $qode_options_elision['scroll_amount_for_sticky'];
        echo "<script>
(function($) {
    $(window).load(function () {
        $(window).unbind();
       
        $(document).on('scroll', function(e) {
            let header = $('header.elision-header-replacement');
            if ($(window).scrollTop() > $scrollAmount && !header.hasClass('solid')) {
                header.addClass('solid');
            } else if ($(window).scrollTop() <= $scrollAmount && header.hasClass('solid')) {
                header.removeClass('solid');                
            }
        });
    })
})(jQuery);

</script>";
    }

    private function replaceSocialShareShortcode()
    {

        /* Social Share shortcode */

        remove_shortcode('social_share');
        add_shortcode('social_share', function ($atts, $content = null) {
            global $qode_options_elision;

            $count_char = is_ssl() ? 23 : 22;

            if (isset($qode_options_elision['twitter_via']) && !empty($qode_options_elision['twitter_via'])) {
                $twitter_via = " via " . $qode_options_elision['twitter_via'];
            } else {
                $twitter_via = "";
            }
            $html = "";
            if (isset($qode_options_elision['enable_social_share']) && $qode_options_elision['enable_social_share'] == "yes") {
                $post_type = get_post_type();
                if (isset($qode_options_elision["post_types_names_$post_type"])) {
                    if ($qode_options_elision["post_types_names_$post_type"] == $post_type) {
                        if ($post_type == "portfolio_page") {
                            $html .= '<div class="portfolio_share">';
                        } elseif ($post_type == "post") {
                            $html .= '<div class="blog_share">';
                        } elseif ($post_type == "page") {
                            $html .= '<div class="page_share">';
                        }
                        $html .= '<span class="social_share_holder">';
                        $html .= '<span class="social_share_icon"></span>';
                        if ($post_type == "post") {
                            $html .= '<span class="social_share_title">' . esc_html__('Share', 'elision-core') . '</span>';
                        }

                        $social_drodown_classes = '';
                        if (isset($qode_options_elision['enable_pinterest']) && $qode_options_elision['enable_pinterest'] == "yes" ||
                            isset($qode_options_elision['enable_linkedin']) && $qode_options_elision['enable_linkedin'] == "yes") {
                            $social_drodown_classes .= 'wider';
                        }
                        $html .= '<div class="social_share_dropdown ' . $social_drodown_classes . '"><ul>';
                        $html .= '<li class="share_title"><span>' . esc_html__('Share on', 'elision-core') . '</span></li>';
                        if (isset($qode_options_elision['enable_facebook_share']) && $qode_options_elision['enable_facebook_share'] == "yes") {
                            $html .= '<li class="facebook_share">';
                            if (wp_is_mobile()) {
                                $html .= '<a title="' . esc_attr__("Share on Facebook", "elision-core") . '" href="javascript:void(0)" onclick="window.open(\'https://m.facebook.com/sharer.php?u=' . urlencode(get_permalink());
                            } else {
                                $html .= '<a title="' . esc_attr__("Share on Facebook", "elision-core") . '" href="javascript:void(0)" onclick="window.open(\'https://www.facebook.com/sharer.php?s=100&amp;p[title]=' . urlencode(elision_qode_addslashes(get_the_title())) . '&amp;p[url]=' . urlencode(get_permalink()) . '&amp;p[images][0]=';
                                if (function_exists('the_post_thumbnail')) {
                                    $html .= wp_get_attachment_url(get_post_thumbnail_id());
                                }
                            }

                            $html .= '&amp;p[summary]=' . urlencode(elision_qode_addslashes(strip_tags(get_the_excerpt())));
                            $html .= '\', \'sharer\', \'toolbar=0,status=0,width=620,height=280\');">';
                            if (!empty($qode_options_elision['facebook_icon'])) {
                                $html .= '<img src="' . $qode_options_elision["facebook_icon"] . '" />';
                            } else {
                                $html .= '<i class="fab fa-facebook"></i>';
                            }
                            $html .= "<span class='share_text'>" . esc_html__('FB', 'elision-core') . "</span>";
                            $html .= "</a>";
                            $html .= "</li>";
                        }

                        if ($qode_options_elision['enable_twitter_share'] == "yes") {
                            $html .= '<li class="twitter_share">';
                            if (wp_is_mobile()) {
                                $html .= '<a href="#" onclick="popUp=window.open(\'https://twitter.com/intent/tweet?text=' . urlencode(elision_qode_the_excerpt_max_charlength($count_char) . $twitter_via) . get_permalink() . '\', \'popupwindow\', \'scrollbars=yes,width=800,height=400\');popUp.focus();return false;">';
                            } else {
                                $html .= '<a href="#" onclick="popUp=window.open(\'https://twitter.com/home?status=' . urlencode(elision_qode_the_excerpt_max_charlength($count_char) . $twitter_via) . get_permalink() . '\', \'popupwindow\', \'scrollbars=yes,width=800,height=400\');popUp.focus();return false;">';
                            }
                            if (!empty($qode_options_elision['twitter_icon'])) {
                                $html .= '<img src="' . $qode_options_elision["twitter_icon"] . '" />';
                            } else {
                                $html .= '<i class="fab fa-twitter"></i>';
                            }
                            $html .= "<span class='share_text'>" . esc_html__('Tweet', 'elision-core') . "</span>";
                            $html .= "</a>";
                            $html .= "</li>";
                        }
                        if ($qode_options_elision['enable_google_plus'] == "yes") {
                            $html .= '<li  class="google_share">';
                            $html .= '<a href="#" onclick="popUp=window.open(\'https://plus.google.com/share?url=' . urlencode(get_permalink()) . '\', \'popupwindow\', \'scrollbars=yes,width=800,height=400\');popUp.focus();return false">';
                            if (!empty($qode_options_elision['google_plus_icon'])) {
                                $html .= '<img src="' . $qode_options_elision['google_plus_icon'] . '" />';
                            } else {
                                $html .= '<i class="fab fa-google-plus"></i>';
                            }
                            $html .= "<span class='share_text'>" . esc_html__('G+', 'elision-core') . "</span>";
                            $html .= "</a>";
                            $html .= "</li>";
                        }
                        if (isset($qode_options_elision['enable_linkedin']) && $qode_options_elision['enable_linkedin'] == "yes") {
                            $html .= '<li  class="linkedin_share">';
                            $html .= '<a href="#" onclick="popUp=window.open(\'https://linkedin.com/shareArticle?mini=true&amp;url=' . urlencode(get_permalink()) . '&amp;title=' . urlencode(get_the_title()) . '\', \'popupwindow\', \'scrollbars=yes,width=800,height=400\');popUp.focus();return false">';
                            if (!empty($qode_options_elision['linkedin_icon'])) {
                                $html .= '<img src="' . esc_url($qode_options_elision['linkedin_icon']) . '" alt="' . esc_attr__('Social Share', 'elision-core') . '" />';
                            } else {
                                $html .= '<i class="fab fa-linkedin"></i>';
                            }
                            $html .= "<span class='share_text'>" . esc_html__("LinkedIn", "elision-core") . "</span>";
                            $html .= "</a>";
                            $html .= "</li>";
                        }
                        if (isset($qode_options_elision['enable_tumblr']) && $qode_options_elision['enable_tumblr'] == "yes") {
                            $html .= '<li  class="tumblr_share">';
                            $html .= '<a href="#" onclick="popUp=window.open(\'https://www.tumblr.com/share/link?url=' . urlencode(get_permalink()) . '&amp;name=' . urlencode(get_the_title()) . '&amp;description=' . urlencode(get_the_excerpt()) . '\', \'popupwindow\', \'scrollbars=yes,width=800,height=400\');popUp.focus();return false">';
                            if (!empty($qode_options_elision['tumblr_icon'])) {
                                $html .= '<img src="' . esc_url($qode_options_elision['tumblr_icon']) . '" alt="' . esc_attr__('Social Share', 'elision-core') . '" />';
                            } else {
                                $html .= '<i class="fab fa-tumblr"></i>';
                            }
                            $html .= "<span class='share_text'>" . esc_html__("Tumblr", "elision-core") . "</span>";
                            $html .= "</a>";
                            $html .= "</li>";
                        }

                        if (isset($qode_options_elision['enable_pinterest']) && $qode_options_elision['enable_pinterest'] == "yes") {
                            $html .= '<li  class="pinterest_share">';
                            $image = $this->getFirstGalleryImageurl();

                            if ($image) {
                                $html .= '<a href="#" onclick="popUp=window.open(\'https://pinterest.com/pin/create/button/?url='
                                    . urlencode(get_permalink()) . '&amp;description=' . esc_attr(get_the_title())
                                    . '&amp;media=' . urlencode($image)
                                    . '\', \'popupwindow\', \'scrollbars=yes,width=800,height=400\');popUp.focus();return false">';
                                if (!empty($qode_options_elision['pinterest_icon'])) {
                                    $html .= '<img src="' . esc_url($qode_options_elision['pinterest_icon']) . '" alt="' . esc_attr__('Social Share', 'elision-core') . '" />';
                                } else {
                                    $html .= '<i class="fab fa-pinterest"></i>';
                                }
                                $html .= "<span class='share_text'>" . esc_html__("Pinterest", "elision-core") . "</span>";
                                $html .= "</a>";
                                $html .= "</li>";
                            }

                        }
                        if (isset($qode_options_elision['enable_vk']) && $qode_options_elision['enable_vk'] == "yes") {
                            $html .= '<li  class="vk_share">';
                            $image = $this->getFirstGalleryImageurl();
                            if ($image) {
                                $html .= '<a href="#" onclick="popUp=window.open(\'https://vkontakte.ru/share.php?url=' . urlencode(get_permalink()) . '&amp;title=' . urlencode(get_the_title()) . '&amp;description=' . urlencode(get_the_excerpt()) . '&amp;image=' . urlencode($image[0]) . '\', \'popupwindow\', \'scrollbars=yes,width=800,height=400\');popUp.focus();return false">';
                                if (!empty($qode_options_elision['vk_icon'])) {
                                    $html .= '<img src="' . esc_url($qode_options_elision['vk_icon']) . '" alt="' . esc_attr__('Social Share', 'elision-core') . '" />';
                                } else {
                                    $html .= '<i class="fab fa-vk"></i>';
                                }
                                $html .= "<span class='share_text'>" . esc_html__("VK", "elision-core") . "</span>";
                                $html .= "</a>";
                                $html .= "</li>";
                            }
                        }

                        $html .= "</ul></div>";
                        $html .= "</span>";
                        if ($post_type == "portfolio_page" || $post_type == "post" || $post_type == "page") {
                            $html .= '</div>';
                        }
                    }
                }
            }
            return $html;
        });
    }

    private function getFirstGalleryImageurl(): string
    {
        global $post;

        $url = '';

        if (in_array($post->post_type, ['exhibitors', 'partners'])) {
            $gallery_data = get_post_meta($post->ID, 'gallery_data', true);
            $image_id = current($gallery_data['image_id'] ?? []);
            $url = interevent_get_attachment_url($image_id, 'full');
        }

        return $url;
    }

    public function fixPluginsUrl($url, $path, $plugin)
    {
        $siteId = get_current_blog_id();
        if (is_main_site($siteId)) {
            return $url;
        }
        $mainSiteId = get_main_site_id();
        $url = str_replace(get_home_url($mainSiteId), get_home_url($siteId), $url);
        return $url;
    }

}
