<?php


namespace Eventman\Includes\Post;


use Eventman\Admin\LogTrait;
use Eventman\Includes\MsEventman;
use threewp_broadcast\api\api;
use threewp_broadcast\actions\broadcasting_finished;
use threewp_broadcast\broadcasting_data;
use Throwable;
use WP_Filesystem_Base;

/**
 * Class PostTypes
 *
 * Sets hooks for the new custom post types
 *
 * @package Eventman\Includes\Post
 */
class PostTypes
{

    /**
     * @var Exhibitor
     */
    private $exhibitor;
    /**
     * @var Partner
     */
    private $partner;
    /**
     * @var ImageGallery
     */
    private $imageGallery;
    /**
     * @var MsEventman
     */
    private $msEventman;

    use LogTrait {
        log as _log;
    }

    public function __construct(MsEventman $msEventman)
    {
        $this->msEventman = $msEventman;
        $this->exhibitor = new Exhibitor();
        $this->partner = new Partner();
        $this->imageGallery = new ImageGallery();
    }

    protected function log($msg)
    {
        $this->_log('PostType: ' . $msg);
    }

    public function createTaxonomies()
    {
        $labels = array(
            'name' => _x('Events', 'ms-eventman'),
            'singular_name' => _x('Event', 'ms-eventman'),
            'search_items' => _x('Search Events', 'ms-eventman'),
            'all_items' => _x('All Events', "ms-eventman"),
            'parent_item' => _x('Parent Event', "ms-eventman"),
            'parent_item_colon' => _x('Parent Event:', "ms-eventman"),
            'edit_item' => _x('Edit Event', "ms-eventman"),
            'update_item' => _x('Update Event', "ms-eventman"),
            'add_new_item' => _x('Add New Event', "ms-eventman"),
            'new_item_name' => _x('New Event Name', "ms-eventman"),
            'menu_name' => _x('Events', "ms-eventman"),
        );

        if (!is_main_site()) {
            register_taxonomy('events', ['exhibitors', 'partners'],
                [
                    'labels' => $labels,
                    'public' => true,
                    'show_in_nav_menus' => true,
                    'show_ui' => true,
                    'show_tagcloud' => true,
                    'hierarchical' => true,
                    'show_admin_column' => true,
                    'query_var' => true,
                    'rewrite' => ['slug' => 'events'],
                    'has_archive' => true,
                    'capabilities' => [
                        'manage_terms' => 'manage_events',
                        'edit_terms' => 'manage_events',
                        'delete_terms' => 'manage_events',
                        'assign_terms' => 'edit_posts'
                    ]
                ]);
            $caps = ['manage_event', 'manage_events', 'manage_events', 'edit_posts'];
            $admin = get_role('administrator');
            foreach ($caps as $cap) {
                $admin->add_cap($cap);
            }
        }
    }

    /**
     * Create the new Exhibitor and Partner post types.
     */
    public function registerPostTypes()
    {

        $this->exhibitor->register();
        $this->partner->register();
    }

    /**
     * Add metadata boxes for the new post types.
     */
    public function addMetaBoxesForPostTypes()
    {
        $this->exhibitor->addMetaBox();
        $this->partner->addMetaBox();
    }

    public function hideAdminMenuIfNeeded()
    {
        if (in_array('partner', wp_get_current_user()->roles) || in_array('exhibitor', wp_get_current_user()->roles)) {
            echo '<style type="text/css">#wpcontent, #footer { margin-left: 0px; }</style><script type="text/javascript">jQuery(document).ready( function($) {$("#adminmenuback, #adminmenuwrap, #icl_div").remove();});</script>';
        }
    }

    public function definePublicHooks()
    {
        // register custom post types
        $this->msEventman->getLoader()->addAction('init', $this, 'registerPostTypes');

        // create events taxonomy
        $this->msEventman->getLoader()->addAction('init', $this, 'createTaxonomies');

        // save metadata for exhibitor
        $this->msEventman->getLoader()->addAction('save_post_exhibitors', $this->exhibitor, 'saveMetaFieldsToDatabase', 9);

        // fix gallery broadcasting for exhibitors
//        $this->msEventman->getLoader()->addAction('updated_post_meta', $this, 'updatedMeta', 100, 4);
//        $this->msEventman->getLoader()->addAction('added_post_meta', $this, 'updatedMeta', 100, 4);

        // after broadcast, fix gallery data, and after broadcast translations
        $this->msEventman->getLoader()->addAction('threewp_broadcast_broadcasting_finished', $this, 'fixGalleryDataAfterBroadcast', 100);
//        $this->msEventman->getLoader()->addAction('threewp_broadcast_broadcasting_finished', $this, 'fixMPTAfterBroadcast', 100);
        $this->msEventman->getLoader()->addAction('threewp_broadcast_broadcasting_finished', $this, 'broadcastTranslation', 101);

        // save metadata for partners
        $this->msEventman->getLoader()->addAction('save_post_partners', $this->partner, 'saveMetaFieldsToDatabase', 9);

        // save properties for image gallery
        $this->msEventman->getLoader()->addAction('save_post_exhibitors', $this->imageGallery, 'saveProperties', 10);

        // add custom fields to events taxonomy
        $this->msEventman->getLoader()->addAction('events_edit_form_fields', $this, 'eventsTaxonomyCustomFields', 10, 2);
        $this->msEventman->getLoader()->addAction('edited_events', $this, 'saveTaxonomyCustomFields', 10, 2);

    }

    public function fixMPTAfterBroadcast($action)
    {
        if (!is_main_site()) {
            $this->log('Not in main site, skipping thumbnail synchronization.');
            return $action;
        }
        $this->log('Fixing MultiplePostThumbnail data after broadcast.');
        $bcd = $action->broadcasting_data;
        $post = $bcd->post;
        $blogs = isset($bcd->broadcast_data->getData()['linked_children']) ? array_keys($bcd->broadcast_data->getData()['linked_children']) : [];

        if ($post->post_type === 'exhibitors') {
            $this->log('Looking for meta key "{post_type}_{***}_thumbnail_id"');

            $api = new api();
            $controller = $api->linking($post->ID);
            $meta = get_post_meta($post->ID);
            foreach ($controller->children() as $blogId => $postId) {
                foreach ($meta as $key => $value) {
                    if (str_starts_with($key, $post->post_type) && str_ends_with($key, '_thumbnail_id')) {
                        $this->log("Suspecting key is MPT meta key: [$key:" . $this->pretty($value) . "]. Checking broadcasts...");
                        if (is_array($value)) {
                            $value = array_pop($value);
                            $this->log("Meta value was array, now is $value...");
                        }

                        $thumbnailController = $api->linking($value);
                        $this->log("Found thumbnail children: " . $this->pretty($thumbnailController->children()));
                        if (!isset($thumbnailController->children()[$blogId])) {
                            $this->log("Broadcast for thumbnail $value not found for blog $blogId, broadcasting...");

                            $api->broadcast_children($value, [$blogId]);
                            $thumbnailController = $api->linking($value);
                        }
                        $thumbnailId = $thumbnailController->children()[$blogId];

                        $this->log("Setting thumbnail id to $thumbnailId with meta key $key to post $postId on blog $blogId...");
                        switch_to_blog($blogId);
                        $this->log('Current meta value: ' . $this->pretty(get_post_meta($postId, $key, true)));
                        if ($res = update_post_meta($postId, $key, $thumbnailId)) {
                            $this->log('Successfully added/updated meta: ' . $res . ', ' . $this->pretty(get_post_meta($postId, $key)));
                        }
                        restore_current_blog();

                        // get the URL of the original image
                        $attachedFileUrl = get_post_meta($value, '_wp_attached_file', true);

                        $this->log("Preparing to copy $attachedFileUrl to image with ID $thumbnailId in blog $blogId.");

                        $res = $this->copyImageToBlog($blogId, $thumbnailId, $attachedFileUrl);

                        $this->log("Copy image result: " . strval($res));
                    }
                }
            }
        } else {
            $this->log('MPT Broadcast not available for post type ' . $post->post_type . '.');
        }
        return $action;
    }


    public function defineAdminHooks()
    {
        // add metaboxes for custom post types
        $this->msEventman->getLoader()->addAction('admin_init', $this, 'addMetaBoxesForPostTypes');

        // add scripts and styles for the image gallery
        $this->msEventman->getLoader()->addAction('admin_head-post.php', $this->imageGallery, 'header');
        $this->msEventman->getLoader()->addAction('admin_head-post-new.php', $this->imageGallery, 'header');

        // hide the admin menu for Exhibitor and Partner accounts
        $this->msEventman->getLoader()->addAction('admin_head', $this, 'hideAdminMenuIfNeeded');
    }

    public function eventsTaxonomyCustomFields($tag)
    {
        $t_id = $tag->term_id;
        $term_meta = get_term_meta($t_id);
        ?>
        <tr class="form-field">
            <th scope="row">
                <label for="exh-overview-title"><?php _e('Title for Exhibitor overview', 'ms-eventman'); ?></label>
            </th>
            <td>
                <input type="text" name="term_meta[exhibitor_overview_title]" id="exh-overview-title" style="width:60%;"
                       value="<?php echo isset($term_meta['exhibitor_overview_title'][0]) ? $term_meta['exhibitor_overview_title'][0] : ''; ?>"><br/>
            </td>
        </tr>
        <tr class="form-field">
            <th scope="row">
                <label for="partner-overview-title"><?php _e('Title for Partner overview', 'ms-eventman'); ?></label>
            </th>
            <td>
                <input type="text" name="term_meta[partner_overview_title]" id="exh-overview-title" style="width:60%;"
                       value="<?php echo isset($term_meta['partner_overview_title'][0]) ? $term_meta['partner_overview_title'][0] : ''; ?>"><br/>
            </td>
        </tr>
        <tr class="form-field">
            <th scope="row">
                <label for="ticket-url"><?php _e('URL to ticket sales', 'ms-eventman'); ?></label>
            </th>
            <td>
                <input type="text" name="term_meta[ticket_url]" id="ticket-url" style="width:60%;"
                       value="<?php echo isset($term_meta['ticket_url'][0]) ? $term_meta['ticket_url'][0] : 'https://'; ?>"><br/>
            </td>
        </tr>
        <tr class="form-field">
            <th scope="row">
                <label for="ticket-url"><?php _e('Location', 'ms-eventman'); ?></label>
            </th>
            <td>
                <input type="text" name="term_meta[event_location]" id="event-location" style="width:60%;"
                       value="<?php echo isset($term_meta['event_location'][0]) ? $term_meta['event_location'][0] : ''; ?>"><br/>
            </td>
        </tr>
        <tr class="form-field">
            <th scope="row">
                <label for="dates-amount"><?php _e('Amount of dates', 'ms-eventman'); ?></label>
            </th>
            <td>
                <input type="number" name="term_meta[date_amount]" id="dates-amount" size="25" style="width:60%;"
                       value="<?php echo $term_meta['date_amount'][0] ? $term_meta['date_amount'][0] : '1'; ?>"><br/>
                <span class="description"><?php _e('Amount of dates for this event', 'ms-eventman'); ?></span>
            </td>
        </tr>
        <tr class="form-field">
            <th scope="row">
                <label for="dates"><?php _e('Dates', 'ms-eventman'); ?></label>
            </th>
            <td id="dates-box">
                <?php
                isset($term_meta['date_amount']) || $term_meta['date_amount'][0] = 0;
                if (!isset($term_meta['date_amount'][0]) || $term_meta['date_amount'][0] == 0) {
                    ?>
                    <div class="dates-box-wrapper">
                        <input type="text" name="term_meta[date_from][]" class="datetime-box" id="date-from-0"
                               value="0"/>
                        <?= _e("Until", 'ms-eventman') ?> <input type="text" name="term_meta[date_till][]"
                                                                 class="datetime-box" id="date-till-0" value="0"/>
                    </div>
                    <?php
                }
                for ($i = 0; $i < $term_meta['date_amount'][0]; $i++) :
                    $priceType = unserialize($term_meta['date_from'][0]);
                    $pricePrice = unserialize($term_meta['date_till'][0]);
                    ?>
                    <div class="dates-box-wrapper">
                        <input type="text" name="term_meta[date_from][]" class="datetime-box" id="date-from-<?= $i ?>"
                               value="<?php echo $priceType[$i] ? $priceType[$i] : '0'; ?>"/>
                        <?= _e("Until", 'ms-eventman') ?> <input type="text" name="term_meta[date_till][]"
                                                                 class="datetime-box" id="date-till-<?= $i ?>"
                                                                 value="<?php echo $pricePrice[$i] ? $pricePrice[$i] : '0'; ?>"/>
                    </div>
                <?php
                endfor;
                ?>
            </td>
        </tr>
        <tr class="form-field">
            <th scope="row">
                <label for="prices-amount"><?php _e('Amount of prices', 'ms-eventman'); ?></label>
            </th>
            <td>
                <input type="number" name="term_meta[prices_amount]" id="prices-amount" style="width:60%;"
                       value="<?php echo $term_meta['prices_amount'][0] ? $term_meta['prices_amount'][0] : '1'; ?>"><br/>
                <span class="description"><?php _e('Amount of prices for this event', 'ms-eventman'); ?></span>
            </td>
        </tr>
        <tr class="form-field">
            <th scope="row">
                <?= _e("Prices", 'ms-eventman') ?>
            </th>
            <td id="prices-box">
                <?php
                if (isset($term_meta['prices'])) {
                    $prices = unserialize($term_meta['prices'][0]);
                }
                isset($term_meta['prices_amount']) || $term_meta['prices_amount'][0] = 0;

                if (!isset($term_meta['prices_amount'][0]) || $term_meta['prices_amount'][0] == 0) {
                    ?>
                    <div class="dates-box-wrapper">
                        <input type="text" name="term_meta[price_type][]" class="price-input-box" id="price-type-0"
                               value="Name"/>
                        <input type="text" name="term_meta[price_price][]" class="price-input-box" id="price-price-0"
                               value="0.00"/>
                    </div>
                    <?php
                }

                for ($i = 0; $i < $term_meta['prices_amount'][0]; $i++) :
                    $priceType = unserialize($term_meta['price_type'][0]);
                    $pricePrice = unserialize($term_meta['price_price'][0]);
                    ?>
                    <div class="prices-box-wrapper">
                        <input type="text" name="term_meta[price_type][]" class="price-input-box"
                               id="price-type-<?= $i ?>" value="<?= $priceType[$i] ?>"/>
                        <input type="text" name="term_meta[price_price][]" class="price-input-box"
                               id="price-price-<?= $i ?>" value="<?= $pricePrice[$i] ?>"/>
                    </div>
                <?php
                endfor;
                ?>
            </td>
        </tr>
        <tr class="form-group">
            <th scope="row">
                <?= _e("Publish", 'ms-eventman') ?>
            </th>
            <td>
                <?php $checked = isset($term_meta['publish']) && $term_meta['publish'][0] === 'on'; ?>
                <input type="checkbox" name="term_meta[publish]" class="publish-input"
                       id="publish-cb" <?= $checked ? 'checked="checked"' : '' ?>>
            </td>
        </tr>
        <?php
    }

    public function saveTaxonomyCustomFields($term_id, $tt_id)
    {
        if (isset($_POST['term_meta'])) {
            $termMeta = has_term_meta($term_id) ? get_term_meta($term_id, '', true) : [];
            $meta = $_POST['term_meta'];

            foreach ($termMeta as $oldKey => $value) {
                if (!isset($meta[$oldKey]) && $oldKey == 'publish') {
                    $meta[$oldKey] = 'off';
                }
                if (!isset($meta[$oldKey]) && $oldKey == 'exhibitors-final') {
                    $meta[$oldKey] = 'off';
                }
            }
            foreach ($meta as $key => $value) {
                if (isset($value)) {
                    $keyMeta = get_term_meta($term_id, $key, true);
                    if (isset($keyMeta)) {
                        update_term_meta($term_id, $key, $value);
                    } else {
                        add_term_meta($term_id, $key, $value);
                    }
                }
            }
        }
    }

    /**
     * @param array $newUploadDir
     * @param $originalUrl
     * @return array|bool
     */
    protected function copyImageToCurrentSite(array $originalUploadDir, array $newUploadDir, $originalUrl)
    {
        $this->log("Copying $originalUrl to site " . get_current_blog_id());

        $explode = explode('/', $originalUrl);
        $fileName = end($explode);


        $fixedAttachmentUrl = (substr($originalUrl, 0, 1) === '/' ? '' : '/') . "$originalUrl";
        $file_url = $originalUploadDir['baseurl'] . $fixedAttachmentUrl;
        $file_type_data = wp_check_filetype(basename($originalUrl), null);
        $file_type = $file_type_data['type'];
        $timeout_seconds = 5;

        $localFile = $newUploadDir['path'] . '/' . $fileName;


        clearstatcache();
        if (file_exists($localFile)) {
            $this->log("File $localFile already present in uploads! skipping.");
            return [
                'file' => $localFile
            ];
        }
        $this->log("File $localFile not found.");
        $this->log("Downloading file $file_url...");
        $tmp = download_url($file_url, $timeout_seconds);
        if (is_wp_error($tmp)) {
            return [
                'error' => $tmp->get_error_data()
            ];
        }

        $file = [
            'name' => basename($file_url),
            'type' => $file_type,
            'tmp_name' => $tmp,
            'error' => 0,
            'size' => filesize($tmp),
        ];

        $this->log('Handling sideload...');
        $overrides = array(
            // Tells WordPress to not look for the POST form
            // fields that would normally be present, default is true,
            // we downloaded the file from a remote server, so there
            // will be no form fields.
            'test_form' => false,
            // Setting this to false lets WordPress allow empty files – not recommended.
            'test_size' => true,
            // A properly uploaded file will pass this test.
            // There should be no reason to override this one.
            'test_upload' => true,
        );
        $sideloadRes = wp_handle_sideload($file, $overrides);

        // If an error occurred while trying to sideload the media file; continue to next blog.
        if (!$sideloadRes) {
            return false;
        } elseif (!empty($sideloadRes['error'])) {
            return $sideloadRes['error'];
        }

        return $sideloadRes;
    }

    /**
     * @param broadcasting_finished $action
     * @return mixed
     */
    public function fixGalleryDataAfterBroadcast($action)
    {
        /** @var broadcasting_data $bcd */
        $bcd = $action->broadcasting_data;
        $post = $bcd->post;

        if ($post->post_type === 'exhibitors') {
            $linked_children = $bcd->broadcast_data->getData()['linked_children'] ?? [];

            if (empty($linked_children)) {
                return $action;
            }

            $this->log("Broadcasting finished on exhibitor ID: " . $post->ID);

            // get the post meta
            $galleryData = get_post_meta($post->ID, 'gallery_data', true);

            $broadcastedDatas = [];

            $api = new api();
            $current_blog_id = get_current_blog_id();
            foreach ($linked_children as $blog_id => $child_post_id) {
                switch_to_blog($blog_id);

                $child_gallery_data = get_post_meta($child_post_id, 'gallery_data', true);
                foreach ($child_gallery_data['image_id'] ?? [] as $idx => $parent_image_id) {
                    $parent_image_controller = $api->linking($current_blog_id, $parent_image_id);
                    $image_children = $parent_image_controller->children();

                    if (!isset($image_children[$blog_id])) {
                        switch_to_blog($current_blog_id);
                        $api->broadcast_children($parent_image_id, [$blog_id]);
                        restore_current_blog();

                        $image_children = $parent_image_controller->children();
                    }

                    $current_blog_image = $image_children[$blog_id];
                    $child_gallery_data['image_id'][$idx] = $current_blog_image;
                }
                $child_gallery_data['blog_id'] = $blog_id;
                update_post_meta($child_post_id, 'gallery_data', $child_gallery_data);


                restore_current_blog();
            }



//            $this->broadcastGalleryData($post->ID, $galleryData, $blogs);
        }

        return $action;
    }

    /**
     * @param $postId
     * @param array $galleryData
     * @param array $blogs
     */
    protected function broadcastGalleryData($postId, $galleryData = [], $blogs = []): void
    {
        if ($postId && !empty($galleryData) && !empty($blogs)) {
            $api = new api(); // threewp broadcast api

            $originalBlogId = $galleryData['blog_id'];
            $imageIds = ($galleryData['image_id'] ?? []);

            $this->log('Starting broadcast gallery data: ' . $this->pretty($galleryData));

            $postChildren = $api->linking($postId);

            foreach ($imageIds as $imageId) {
                $controller = $api->linking($imageId);
                $childBlogsImage = $controller->children();

                $blogIdsLeft = array_diff($blogs, array_keys($childBlogsImage));
                $this->log(sprintf("Image already has a broadcasted copy in %s, wanted blogs: %s, diff: %s",
                    $this->pretty(array_keys($childBlogsImage)),
                    $this->pretty($blogs),
                    $this->pretty($blogIdsLeft)));

                $data = $api->broadcast_children($imageId, $blogIdsLeft);

                $this->log("Broadcasted image $imageId to blogs " . $this->pretty($blogIdsLeft));

                // images are now linked to blogs, initialize linking controller
                $imageLinking = $api->linking($originalBlogId, $imageId);
                $children = $imageLinking->children();

                $this->log("Got children data: " . $this->pretty($children));

                foreach ($children as $blogId => $broadcastedImageId) {
                    if (!in_array($blogId, $blogIdsLeft)) {
                        $this->log("Blog $blogId is already correctly setup, skipping...");
//                        continue;
                    }
                    // get the URL of the original image
                    $attachedFileUrl = get_post_meta($imageId, '_wp_attached_file', true);

                    $this->log("Preparing to copy $attachedFileUrl to image with ID $broadcastedImageId in blog $blogId.");

                    $res = $this->copyImageToBlog($blogId, $broadcastedImageId, $attachedFileUrl);

                    $this->log("Copy image result: " . strval($res));

                    if (!isset($postChildren[$blogId])) {
                        $this->log("No entry found for blog $blogId in " . $this->pretty($postChildren));
                        continue;
                    }
                    $childPostId = $postChildren[$blogId];

                    // switch to child blog
                    switch_to_blog($blogId);
                    $this->log("Switched to blog $blogId to modify gallery_data metadata on post $childPostId.");

                    // get data or create new gallery data
                    $broadcastedGalleryData = get_post_meta($childPostId, 'gallery_data', true);
                    if (!$broadcastedGalleryData) {
                        $freshGalleryData = ['blog_id' => $blogId, 'image_id' => []];
                        add_post_meta($childPostId, 'gallery_data', $freshGalleryData);
                        $broadcastedGalleryData = get_post_meta($childPostId, 'gallery_data', true);
                    }

                    $this->log("Gallery data (post $childPostId) BEFORE modification: " . $this->pretty($broadcastedGalleryData));

                    // set blog ID
                    $broadcastedGalleryData['blog_id'] = $blogId;

                    // get the image ids
                    $imageIdsBroadcastedGallery = $broadcastedGalleryData['image_id'];

                    $this->log("Trying to replace $imageId with $broadcastedImageId in " . $this->pretty($imageIdsBroadcastedGallery));

                    // flip to find value index
                    $flipped = array_flip($imageIdsBroadcastedGallery);
                    if (isset($flipped[$imageId])) {
                        $this->log("Found $imageId at postition " . $flipped[$imageId]);
                        $broadcastedGalleryData['image_id'][$flipped[$imageId]] = $broadcastedImageId;
                    } else {
                        $this->log("Could not find $imageId in array.");
                    }

                    $this->log(sprintf("Gallery data (post $childPostId) AFTER modification: %s. Updating meta field...", $this->pretty($broadcastedGalleryData)));

                    update_post_meta($childPostId, 'gallery_data', $broadcastedGalleryData);

                    $this->log('Restoring previous blog...');
                    restore_current_blog();
                }
                $this->log("Fixed gallery data for all childposts of image $imageId.");
            }
        }
    }

    /**
     * @param $toBlog
     * @param $newImageId
     * @param $originalFileUrl
     * @return bool true if succeeded
     */
    protected function copyImageToBlog($toBlog, $newImageId, $originalFileUrl)
    {
        if (get_current_blog_id() != $toBlog) {
            $fromUploadDir = wp_get_upload_dir();
        }
        switch_to_blog($toBlog);
        // get the upload dir of the current site
        $currentUploadDir = wp_get_upload_dir();
        $fromUploadDir = $fromUploadDir ?? $currentUploadDir;

        // set image meta if copy succeeded
        if (is_array($uploadRes = $this->copyImageToCurrentSite($fromUploadDir, $currentUploadDir, $originalFileUrl))
            && !isset($uploadRes['error'])) {
            $this->log('Sideload results: ' . $this->pretty($uploadRes));
            // generate meta for the new file
            $meta = wp_generate_attachment_metadata($newImageId, $uploadRes['file']);

            // update meta for attachment
            wp_update_attachment_metadata($newImageId, $meta);

            // update the attached file field
            update_post_meta($newImageId, '_wp_attached_file', $meta['file']);

            $this->log('Image copied successfully.');
            $succeeded = true;
        } else {
            $this->log('Failed to copy image: ' . $this->pretty($uploadRes));
            $succeeded = false;
        }
        restore_current_blog();

        return $succeeded;
    }

    /**
     * Broadcast translations for the post referenced in $action.
     * @param $action
     * @return mixed
     */
    public function broadcastTranslation($action)
    {
        global $sitepress;

        if (is_main_site()) {
            $bcd = $action->broadcasting_data;
            $post = $bcd->post;
            $blogs = isset($bcd->broadcast_data->getData()['linked_children']) ? array_keys($bcd->broadcast_data->getData()['linked_children']) : [];

            if (in_array($post->post_type, ['exhibitors', 'partners', 'post', 'page'])) {
                // terminate if wpml is not present
                if (!isset($bcd->wpml)) {
                    $this->log('No WPML data present, skipping.');
                    return $action;
                } elseif ($bcd->wpml->language !== $sitepress->get_default_language()) {
                    $this->log('Post is translation, skipping.');
                    return $action;
                }

                $this->log('Preparing to broadcast translations for post ' . $post->ID);
                $postLang = $bcd->wpml->language;
                $translations = $bcd->wpml->translations;
                unset($translations[$postLang]);

                if (empty($translations)) {
                    $this->log('No translations found for post ' . $post->ID . ', stopping...');
                    return $action;
                }
                $this->log("Found " . count($translations) . ' translations: ' . $this->pretty($translations));

                foreach ($translations as $language => $translatedPostId) {
                    $this->log("Preparing to broadcast $language translation with ID $translatedPostId");

                    $api = new api();
                    $api->broadcast_children($translatedPostId, $blogs);
                    $controller = $api->linking($translatedPostId);

                    $this->log("Broadcasted translated post $translatedPostId: " . $this->pretty($controller->children()));
                }

                $this->log("Translations for post " . $post->ID . ' completed, exiting...');
            } else {
                $this->log('Posttype ' . $post->post_type . ' not available for automated translation broadcast.');
            }
        } else {
            $this->log('No automated translation broadcasts for non-main sites.');
        }

        return $action;
    }

    /**
     * @param $newMeta
     * @param $post_id
     * @param $metaKey
     * @return mixed
     */
    protected function broadcastMultiplePosthumbnails($newMeta, $post_id, $metaKey)
    {
        if (!is_main_site()) {
            global $wp_current_filter;

            // check if we're broadcasting the meta at this moment
            if (in_array('threewp_broadcast_broadcast_post', $wp_current_filter)) {
                $api = new api();

                // get the linking for the attachment
                $controller = $api->linking(get_main_site_id(), $newMeta);
                $children = $controller->children();

                if (array_key_exists(get_current_blog_id(), $children)) {
                    // attachment has already been broadcasted before, set the broadcasted id as meta value
                    update_post_meta($post_id, $metaKey, $children[get_current_blog_id()], $newMeta);
                } else {
                    // attachment has not been broadcasted, do broadcast now
                    $currentBlog = get_current_blog_id();

                    switch_to_blog(get_main_site_id());
                    $mainSiteUploadDir = wp_upload_dir();
                    $api->broadcast_children($newMeta, [$currentBlog]);
                    restore_current_blog();

                    $controller = $api->linking(get_main_site_id(), $newMeta);
                    $children = $controller->children();
                    if (isset($children[get_current_blog_id()])) {
                        // attachment has been broadcasted, fix urls and set the broadcasted id as meta value

                        // fix urls
                        $childPostId = $children[get_current_blog_id()];
                        $attachmentUrl = get_post_meta($childPostId, '_wp_attached_file', true);

                        // set image meta if copy succeeded
                        try {
                            if (is_array($uploadRes = $this->copyImageToCurrentSite($mainSiteUploadDir, $attachmentUrl))) {
                                $meta = wp_generate_attachment_metadata($childPostId, $uploadRes['file']);
                                wp_update_attachment_metadata($childPostId, $meta);
                                update_post_meta($childPostId, '_wp_attached_file', $meta['file']);
                            }
                        } catch (Throwable $t) {
                            // TODO: ERROR LOGGING, ADD HANDLING FOR FAILED IMAGE COPY nb
                            error_log("Error while copying file to site with id " . get_current_blog_id());
                        }

                        update_post_meta($post_id, $metaKey, $childPostId, $newMeta);
                    }
                }

            }
        }
    }

}