<?php

namespace Eventman\Includes\Views;

use Eventman\Includes\Post\CustomPostType;
use MultiPostThumbnails;
use threewp_broadcast\api\api;
use WP_List_Table;
use WP_Post;

/**
 * Class BroadcastListTable.
 *
 * A WP_List_Table to broadcast posts from the main site to other sites in the network.
 *
 * @package Eventman\Includes\Views
 */
class BroadcastListTable extends WP_List_Table
{

    /**
     * @var string
     */
    private $postType;

    public function __construct($postType)
    {
        parent::__construct(['ajax' => false, 'singular' => $postType, 'plural' => $postType]);
        $this->postType = $postType;
    }

    /**
     * Handles the checkbox column output.
     *
     * @param WP_Post $post The current WP_Post object.
     * @since 4.3.0
     *
     */
    public function column_cb($post)
    {
        $out = sprintf('<input id="cb-select-%s" type="checkbox" name="post[]" value="%s" />', $post->ID, $post->ID);

        $out .= '<div class="locked-indicator">
                <span class="locked-indicator-icon" aria-hidden="true"></span>
                <span class="screen-reader-text">';
        if (wp_check_post_lock($post->ID)) {
            $out .= printf(__('&#8220;%s&#8221; is locked', 'ms-eventman'), $post->post_title);
        }
        $out .= '</span></div>';
        echo $out;
    }

    /**
     * Prepare the posts for display.
     */
    public function prepare_items()
    {
        // switch to the main site
        $currentBlogId = get_current_blog_id();
        switch_to_blog(get_main_site_id());
        global $wpdb;

        // apply pagination
        $per_page = 20;
        $current_page = $this->get_pagenum();
        if (1 < $current_page) {
            $offset = $per_page * ($current_page - 1);
        } else {
            $offset = 0;
        }

        $search = '';
        $selectedBlogId = $currentBlogId;
        $api = new api();

        if (!empty($_POST) && isset($_POST['_wpnonce'])) {
            if (!wp_verify_nonce($_POST['_wpnonce'], 'bulk-' . $this->_args['plural'])) {
                wp_die(print_r('Nonce invalid'));
            }
            $requestedAction = $_REQUEST['action'];
            if ($requestedAction == -1) {
                $broadcastAction = $_REQUEST['broadcast-action'];
                if (!empty($broadcastAction)) {
                    $postId = $this->broadcastActions($broadcastAction, $api, $selectedBlogId);
                }

                // apply broadcasts
                if (!empty($_REQUEST['broadcast'])) {
                    foreach (array_keys($_REQUEST['broadcast']) as $postId) {
                        $this->broadcastPost($api, $postId, $selectedBlogId);
                    }
                }

            } else {
                // bulk actions
                $this->bulkBroadcastActions($requestedAction, $api, $selectedBlogId);
            }
        }

        // apply search
        if (!empty($_REQUEST['s'])) {
            $search = esc_sql($wpdb->esc_like($_REQUEST['s']));
        }

        // apply ordering
        $orderBy = (!empty($_GET['orderby'])) ? $_GET['orderby'] : 'ID';
        $order = (!empty($_GET['order'])) ? $_GET['order'] : 'ASC';

        // get the posts
        $posts = get_posts([
            'post_type' => $this->postType,
            'post_status' => array_filter(
                CustomPostType::allStatuses(),
                function ($s) {
                    return $s != 'trash';
                }),
            'orderby' => $orderBy,
            'order' => $order,
            'offset' => $offset,
            'nopaging' => true,
            's' => $search]);

        // generate the columns
        $items = $posts;
        $columns = $this->get_columns();
        $hidden = array();
        $sortable = $this->get_sortable_columns();
        $this->_column_headers = array($columns, $hidden, $sortable);
        $count = sizeof($posts);

        $this->items = $items;

        // Set the pagination
        $this->set_pagination_args(array(
            'total_items' => $count,
            'per_page' => $per_page,
            'total_pages' => ceil($count / $per_page)
        ));

        // switch back to the current blog
        switch_to_blog($currentBlogId);
    }

    /**
     * @param api $api
     * @param $postId
     * @param int $selectedBlogId
     * @param $selectedBlogPostId
     */
    protected function trashBroadcast(api $api, $postId, int $selectedBlogId, $selectedBlogPostId): void
    {
        $api->unlink($postId, [$selectedBlogId]);
        switch_to_blog($selectedBlogId);
        wp_trash_post($selectedBlogPostId);
        restore_current_blog();
    }

    /**
     * @param api $api
     * @param $postId
     * @param int $selectedBlogId
     * @param $selectedBlogPostId
     */
    protected function deleteBroadcast(api $api, $postId, int $selectedBlogId, $selectedBlogPostId): void
    {
        $api->unlink($postId, [$selectedBlogId]);
        switch_to_blog($selectedBlogId);
        wp_delete_post($selectedBlogPostId);
        restore_current_blog();
    }

    /**
     * @param api $api
     * @param $postId
     * @param int $selectedBlogId
     */
    protected function broadcastPost(api $api, $postId, int $selectedBlogId): void
    {
        $api->find_unlinked_children($postId, [$selectedBlogId]);

        $controller = $api->linking(get_main_site_id(), $postId);

        if (!in_array($selectedBlogId, array_keys($controller->children()))) {
            $api->broadcast_children($postId, [$selectedBlogId]);
            //                    $controller->link($selectedBlogId);
        }
    }

    public function get_columns()
    {
        return [
            'cb' => '<input type="checkbox" />',
            'ID' => __("ID", "ms-eventman"),
            'publish' => __("Publish", "ms-eventman"),
            'from' => __("From Site", "ms-eventman"),
            'post_title' => __("Title", "ms-eventman"),
            'removeAction' => __("Remove", "ms-eventman"),
        ];
    }

    protected function get_sortable_columns()
    {
        return [
            'ID' => ['ID', true],
            'post_title' => ['post_title', true],
        ];
    }

    /**
     * Displays the table.
     *
     * @since 3.1.0
     */
    public function display()
    {
        $singular = $this->_args['singular'];

        $this->display_tablenav('top');

        $this->screen->render_screen_reader_content('heading_list');
        ?>
        <table class="wp-list-table <?php echo implode(' ', $this->get_table_classes()); ?>">
            <thead>
            <tr>
                <?php $this->print_column_headers(); ?>
            </tr>
            </thead>

            <tbody id="the-list"
                <?php
                if ($singular) {
                    echo " data-wp-lists='list:$singular'";
                }
                ?>
            >
            <?php $this->display_rows_or_placeholder(); ?>
            </tbody>

            <tfoot>
            <tr>
                <?php $this->print_column_headers(false); ?>
            </tr>
            </tfoot>

        </table>
        <?php
        $this->display_tablenav('bottom');
    }

    /**
     * Generate the table navigation above or below the table
     *
     * @param string $which
     * @since 3.1.0
     */
    protected function display_tablenav($which)
    {
        if ('top' === $which) {
            wp_nonce_field('bulk-' . $this->_args['plural']);
        }
        ?>
        <div class="tablenav <?php echo esc_attr($which); ?>">

            <?php if ($this->has_items()) : ?>
                <div class="alignleft actions bulkactions">
                    <?php $this->bulk_actions($which); ?>
                </div>
            <?php
            endif;
            $this->extra_tablenav($which);
            $this->pagination($which);
            ?>

            <br class="clear"/>
        </div>
        <?php
    }

    protected function extra_tablenav($which)
    {
    }

    /**
     * Display the pagination.
     *
     * @param string $which
     * @since 3.1.0
     *
     */
    protected function pagination($which)
    {
        if (empty($this->_pagination_args)) {
            return;
        }

        $total_items = $this->_pagination_args['total_items'];
        $total_pages = $this->_pagination_args['total_pages'];
        $infinite_scroll = false;
        if (isset($this->_pagination_args['infinite_scroll'])) {
            $infinite_scroll = $this->_pagination_args['infinite_scroll'];
        }

        if ('top' === $which && $total_pages > 1) {
            $this->screen->render_screen_reader_content('heading_pagination');
        }
        $output = '<span class="displaying-num">' . sprintf(
            /* translators: %s: Number of items. */
                _n("%s item", "%s items", $total_items),
                number_format_i18n($total_items)
            ) . '</span>';

        $current = $this->get_pagenum();
        $removable_query_args = wp_removable_query_args();

        $current_url = set_url_scheme('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);

        $current_url = remove_query_arg($removable_query_args, $current_url);

        $page_links = array();

        $total_pages_before = '<span class="paging-input">';
        $total_pages_after = '</span></span>';

        $disable_first = false;
        $disable_last = false;
        $disable_prev = false;
        $disable_next = false;

        if ($current == 1) {
            $disable_first = true;
            $disable_prev = true;
        }
        if ($current == 2) {
            $disable_first = true;
        }
        if ($current == $total_pages) {
            $disable_last = true;
            $disable_next = true;
        }
        if ($current == $total_pages - 1) {
            $disable_last = true;
        }

        if ($disable_first) {
            $page_links[] = '<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&laquo;</span>';
        } else {
            $page_links[] = sprintf(
                "<a class='first-page button' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
                esc_url(remove_query_arg('paged', $current_url)),
                __('First page'),
                '&laquo;'
            );
        }

        if ($disable_prev) {
            $page_links[] = '<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&lsaquo;</span>';
        } else {
            $page_links[] = sprintf(
                "<a class='prev-page button' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
                esc_url(add_query_arg('paged', max(1, $current - 1), $current_url)),
                __('Previous page'),
                '&lsaquo;'
            );
        }

        if ('bottom' === $which) {
            $html_current_page = $current;
            $total_pages_before = '<span class="screen-reader-text">' . __('Current Page') . '</span><span id="table-paging" class="paging-input"><span class="tablenav-paging-text">';
        } else {
            $html_current_page = sprintf(
                "%s<input class='current-page' id='current-page-selector' type='text' name='paged' value='%s' size='%d' aria-describedby='table-paging' /><span class='tablenav-paging-text'>",
                '<label for="current-page-selector" class="screen-reader-text">' . __('Current Page') . '</label>',
                $current,
                strlen($total_pages)
            );
        }
        $html_total_pages = sprintf("<span class='total-pages'>%s</span>", number_format_i18n($total_pages));
        $page_links[] = $total_pages_before . sprintf(
            /* translators: 1: Current page, 2: Total pages. */
                _x('%1$s of %2$s', 'paging'),
                $html_current_page,
                $html_total_pages
            ) . $total_pages_after;

        if ($disable_next) {
            $page_links[] = '<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&rsaquo;</span>';
        } else {
            $page_links[] = sprintf(
                "<a class='next-page button' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
                esc_url(add_query_arg('paged', min($total_pages, $current + 1), $current_url)),
                __('Next page'),
                '&rsaquo;'
            );
        }

        if ($disable_last) {
            $page_links[] = '<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&raquo;</span>';
        } else {
            $page_links[] = sprintf(
                "<a class='last-page button' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
                esc_url(add_query_arg('paged', $total_pages, $current_url)),
                __('Last page'),
                '&raquo;'
            );
        }

        $pagination_links_class = 'pagination-links';
        if (!empty($infinite_scroll)) {
            $pagination_links_class .= ' hide-if-js';
        }
        $output .= "\n<span class='$pagination_links_class'>" . join("\n", $page_links) . '</span>';

        if ($total_pages) {
            $page_class = $total_pages < 2 ? ' one-page' : '';
        } else {
            $page_class = ' no-pages';
        }
        $this->_pagination = "<div class='tablenav-pages{$page_class}'>$output</div>";

        echo $this->_pagination;
    }

    protected function get_bulk_actions()
    {
        return [
            'broadcast' => __("Publish", 'ms-eventman'),
            'unlink' => __("Unlink", 'ms-eventman'),
            'trash' => __("Trash", 'ms-eventman'),
            'delete' => __("Delete", 'ms-eventman')];
    }

    /**
     * @param WP_Post $item
     * @param string $column_name
     * @return mixed|string|void
     */
    protected function column_default($item, $column_name)
    {
        $api = new api();
        $children = $api->linking($item->ID)->children();

        $out = '';

        switch_to_blog(get_main_site_id());
        $editLink = get_edit_post_link($item);
        switch ($column_name) {
            case 'ID':
                $out = sprintf('<a href="%s">%s</a>', $editLink, $item->ID);
                break;
            case 'post_title':
                $out = sprintf('<a href="%s">%s</a>', $editLink, $item->post_title);
                break;
            case 'thumbnail':
                if ($item->post_type == 'exhibitors' && class_exists('MultiPostThumbnails')) {
                    if (MultiPostThumbnails::has_post_thumbnail($item->post_type, 'overview-thumbnail', $item->ID)) {
                        $thumbnailUrl = MultiPostThumbnails::get_post_thumbnail_url($item->post_type, 'overview-thumbnail', $item->ID);
                        $thumbnailId = MultiPostThumbnails::get_post_thumbnail_id($item->post_type, 'overview-thumbnail', $item->ID);
                        $thumbnailAlt = null;
                        if (has_meta($thumbnailId)) {
                            $thumbnailAlt = get_post_meta($thumbnailId,'_wp_attachment_image_alt', true);
                        }
                        $out = sprintf('<img src="%s" alt="%s" class="table-img" />', $thumbnailUrl, $thumbnailAlt == null ? 'Thumbnail' : $thumbnailAlt);
                        break;
                    }
                }
                $hasPostThumbnail = has_post_thumbnail($item->ID);
                $thumbnailUrl = $hasPostThumbnail ? get_the_post_thumbnail_url($item->ID) : plugins_url('ms-eventman/img/default_exhibitor.png', 'ms-eventman');
                $thumbnailAlt = $hasPostThumbnail ? get_the_post_thumbnail_caption($item->ID) : "No Thumbnail";
                $out = sprintf('<img src="%s" alt="%s" class="table-img" />', $thumbnailUrl, $thumbnailAlt);
                break;
            case 'publish':
                restore_current_blog();
                $controller = $api->linking(get_main_site_id(), $item->ID);
                $checked = isset($controller->children()[get_current_blog_id()]);
                $checkedAttr = $checked ? 'checked="checked"' : '';
                $checkedState = $checked ? 'true' : 'false';
                $out = sprintf('<label for="publish-check-%s">%s </label><input type="checkbox" id="publish-check-%s" name="broadcast[%s]" data-checked="%s" %s />', $item->ID, __("Published", "ms-eventman"), $item->ID, $item->ID, $checkedState, $checkedAttr);
                switch_to_blog(get_main_site_id());
                break;
            case 'removeAction':
                $tmp = sprintf('<select name="broadcast-action[%s]" id="broadcast-action-select-%s" disabled="disabled">', $item->ID, $item->ID);
                foreach (['unlink' => __("Unlink", 'ms-eventman'), 'trash' => __("Trash", 'ms-eventman'), 'delete' => __("Delete", 'ms-eventman')] as $action => $text) {
                    $tmp .= sprintf('<option value="%s">%s</option>', $action, $text);
                }
                $out = $tmp . '</select>';
                break;
            case 'from':
                switch_to_blog(get_main_site_id());
                $out = get_site(get_current_blog_id())->blogname;
                restore_current_blog();
                break;
            default:
                $out = print_r($item, true); //Show the whole array for troubleshooting purposes
                break;
        }

        restore_current_blog();
        return $out;
    }

    protected function get_views()
    {
        $views = array();
//        $current = ( !empty($_REQUEST['customvar']) ? $_REQUEST['customvar'] : 'all');
//        $current = 'all';
//        //All link
//        $class = ($current == 'all' ? ' class="current"' :'');
//        $all_url = remove_query_arg('customvar');
//        $views['all'] = "<a href='{$all_url }' {$class} >All</a>";
//
//        //Recovered link
//        $foo_url = add_query_arg('customvar','recovered');
//        $class = ($current == 'recovered' ? ' class="current"' :'');
//        $views['recovered'] = "<a href='{$foo_url}' {$class} >Recovered</a>";
//
//        //Abandon
//        $bar_url = add_query_arg('customvar','abandon');
//        $class = ($current == 'abandon' ? ' class="current"' :'');
//        $views['abandon'] = "<a href='{$bar_url}' {$class} >Abandon</a>";

        return $views;
    }

    /**
     * @param $broadcastAction
     * @param api $api
     * @param int $selectedBlogId
     * @return int|string
     */
    protected function broadcastActions($broadcastAction, api $api, int $selectedBlogId)
    {
        foreach ($broadcastAction as $postId => $action) {
            $selectedBlogPostId = $api->linking(get_main_site_id(), $postId)->children()[$selectedBlogId];
            switch ($action) {
                case 'unlink':
                    $api->unlink($postId, [$selectedBlogId]);
                    break;
                case 'trash':
                    $this->trashBroadcast($api, $postId, $selectedBlogId, $selectedBlogPostId);
                    break;
                case 'delete':
                    $this->deleteBroadcast($api, $postId, $selectedBlogId, $selectedBlogPostId);
                    break;
                default:
                    break;
            }

        }
        return $postId;
    }

    /**
     * @param $requestedAction
     * @param api $api
     * @param int $selectedBlogId
     */
    protected function bulkBroadcastActions($requestedAction, api $api, int $selectedBlogId): void
    {
        switch ($requestedAction) {
            case 'broadcast':
                // apply broadcasts
                if (!empty($_REQUEST['post'])) {
                    foreach ($_REQUEST['post'] as $postId) {
                        $this->broadcastPost($api, $postId, $selectedBlogId);
                    }
                }
                break;
            case 'unlink':
                if (!empty($_REQUEST['post'])) {
                    foreach ($_REQUEST['post'] as $postId) {
                        $api->unlink($postId, [$selectedBlogId]);
                    }
                }
                break;
            case 'trash':
                if (!empty($_REQUEST['post'])) {
                    foreach ($_REQUEST['post'] as $postId) {
                        $selectedBlogPostId = $api->linking(get_main_site_id(), $postId)->children()[$selectedBlogId];
                        $this->trashBroadcast($api, $postId, $selectedBlogId, $selectedBlogPostId);
                    }
                }
                break;
            case 'delete':
                if (!empty($_REQUEST['post'])) {
                    foreach ($_REQUEST['post'] as $postId) {
                        $selectedBlogPostId = $api->linking(get_main_site_id(), $postId)->children()[$selectedBlogId];
                        $this->deleteBroadcast($api, $postId, $selectedBlogId, $selectedBlogPostId);
                    }
                }
                break;
            default:
                break;
        }
    }
}