<?php
/**
 * Prohibit direct script loading
 */
defined('ABSPATH') || die('No direct script access allowed!');

if (!class_exists('WP_List_Table')) {
    require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php');
}

/**
 * Class WpmsGscTable
 */
class WpmsGscTable extends WP_List_Table
{
    /**
     * Search string
     *
     * @var mixed
     */
    private $search_string;
    /**
     * Current view
     *
     * @var string
     */
    private $current_view;
    /**
     * Per page
     *
     * @var integer
     */
    private $per_page = 20;
    /**
     * Current page
     *
     * @var integer
     */
    private $current_page = 1;
    /**
     * Box height params
     *
     * @var array
     */
    private $box_height = array(
        'create'         => 350,
        'no_wpms_addon'  => 125,
        'already_exists' => 150,
    );

    /**
     * WpmsGscTable constructor.
     *
     * @param array|string $platform Platform
     * @param string       $category Category
     * @param array        $items    List items
     */
    public function __construct($platform, $category, array $items)
    {
        parent::__construct();
        // search string
        $search_string = filter_input(INPUT_GET, 's');
        if (isset($search_string) && $search_string !== '') {
            $this->search_string = $search_string;
        }
        // Add thickbox
        add_thickbox();

        $this->current_view = $category;
        // Set issue source
        $this->showFields($platform);
        $this->items = $items;
    }

    /**
     * Getting the screen id from this table
     *
     * @return string
     */
    public function getScreenId()
    {
        return $this->screen->id;
    }

    /**
     * Prepares the list of items for displaying.
     *
     * @return void
     */
    public function prepare_items() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- extends from WP_List_Table class
    {
        // Get variables
        $this->per_page     = $this->get_items_per_page('errors_per_page', $this->per_page);
        $paged              = filter_input(INPUT_GET, 'paged');
        $this->current_page = intval(($paged) ? $paged : 1);
        $this->setupColumns();
        $this->views();
        $this->parseItems();
    }

    /**
     * Displays the search box.
     *
     * @param string $text     The 'submit' button label.
     * @param string $input_id ID attribute value for the search input field.
     *
     * @return void
     */
    public function searchBox($text, $input_id)
    {
        // phpcs:disable WordPress.Security.NonceVerification.Recommended -- No action, nonce is not required
        if (empty($_REQUEST['s']) && !$this->has_items()) {
            return;
        }

        $input_id = $input_id . '-search-input';

        if (!empty($_REQUEST['orderby'])) {
            echo '<input type="hidden" name="orderby" value="' . esc_attr($_REQUEST['orderby']) . '" />';
        }
        if (!empty($_REQUEST['order'])) {
            echo '<input type="hidden" name="order" value="' . esc_attr($_REQUEST['order']) . '" />';
        }
        if (!empty($_REQUEST['post_mime_type'])) {
            echo '<input type="hidden" name="post_mime_type" value="' . esc_attr($_REQUEST['post_mime_type']) . '" />';
        }
        if (!empty($_REQUEST['detached'])) {
            echo '<input type="hidden" name="detached" value="' . esc_attr($_REQUEST['detached']) . '" />';
        }
        // phpcs:enable
        ?>
        <p class="search-box">
            <label class="screen-reader-text" for="<?php echo esc_attr($input_id); ?>"><?php echo esc_html($text); ?>:</label>
            <input type="text" id="<?php echo esc_attr($input_id); ?>" class="wpms-search-input" name="s"
                   value="<?php _admin_search_query(); ?>" placeholder="<?php esc_html_e('Search block', 'wpmsPro') ?>"/>
            <button type="submit" id="search-submit"><span class="dashicons dashicons-search"></span></button>
        </p>
        <?php
    }

    /**
     * Set the table columns
     *
     * @return array
     */
    public function get_columns() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- extends from WP_List_Table class
    {
        $columns = array(
            'cb'             => '<input type="checkbox" />',
            'url'            => esc_html__('URL', 'wpmsPro'),
            'last_crawled'   => esc_html__('Last crawled', 'wpmsPro'),
            'first_detected' => esc_html__('First detected', 'wpmsPro'),
            'response_code'  => esc_html__('Response code', 'wpmsPro'),
        );

        return $columns;
    }

    /**
     * Return the columns that are sortable
     *
     * @return array
     */
    protected function get_sortable_columns() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- extends from WP_List_Table class
    {
        $sortable_columns = array(
            'url'            => array('url', false),
            'last_crawled'   => array('last_crawled', false),
            'first_detected' => array('first_detected', false),
            'response_code'  => array('response_code', false),
        );

        return $sortable_columns;
    }

    /**
     * Return available bulk actions
     *
     * @return array
     */
    protected function get_bulk_actions() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- extends from WP_List_Table class
    {
        return array(
            'mark_as_fixed' => esc_html__('Mark as fixed', 'wpmsPro'),
        );
    }

    /**
     * Default method to display a column
     *
     * @param array  $item        Data array.
     * @param string $column_name Column name key.
     *
     * @return mixed
     */
    protected function column_default($item, $column_name) // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- extends from WP_List_Table class
    {
        return $item[$column_name];
    }

    /**
     * Checkbox column
     *
     * @param array $item Current item
     *
     * @return string
     */
    protected function column_cb($item) // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- extends from WP_List_Table class
    {
        return sprintf(
            '<input type="checkbox" name="wpms_crawl_issues[]" value="%s" />',
            $item['url']
        );
    }

    /**
     * Format output to a dateformat
     *
     * @param array $item Current item
     *
     * @return string
     */
    protected function column_last_crawled($item) // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- extends from WP_List_Table class
    {
        return date_i18n(get_option('date_format'), strtotime($item['last_crawled']));
    }

    /**
     * Format output to a dateformat
     *
     * @param array $item Current item
     *
     * @return string
     */
    protected function column_first_detected($item) // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- extends from WP_List_Table class
    {
        return date_i18n(get_option('date_format'), strtotime($item['first_detected']));
    }

    /**
     * URL column
     *
     * @param array $item Current item
     *
     * @return string
     */
    protected function column_url($item) // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- extends from WP_List_Table class
    {
        $actions = array();

        if ($this->canCreateRedirect()) {
            $box_height = $this->modalBox($item['url']);

            $actions['create_redirect'] = '<a title="' . esc_html__('Create a redirect', 'wpmsPro') . '"
             href="#TB_inline?width=600&height=' . $this->box_height[$box_height] . '&inlineId=redirect-' . md5($item['url']) . '"
              class="thickbox">' . esc_html__('Create redirect', 'wpmsPro') . '</a>';
        }

        $actions['view']        = '<a href="' . $item['url'] . '" target="_blank">' . esc_html__('View', 'wpmsPro') . '</a>';
        $actions['markasfixed'] = '<a href="javascript:wpms_mark_as_fixed(\'' . urlencode($item['url']) . '\');">
        ' . esc_html__('Mark as fixed', 'wpmsPro') . '</a>';

        return sprintf(
            '<span class="value">%1$s</span> %2$s',
            $item['url'],
            $this->row_actions($actions)
        );
    }

    /**
     * Running the setup of the columns
     *
     * @return void
     */
    private function setupColumns()
    {
        $this->_column_headers = array($this->get_columns(), array(), $this->get_sortable_columns());
    }

    /**
     * Check if the current category allow creating redirects
     *
     * @return boolean
     */
    private function canCreateRedirect()
    {
        return in_array($this->current_view, array('soft_404', 'not_found', 'access_denied'));
    }

    /**
     * Setting the table navigation
     *
     * @param integer $total_items    Total number of items.
     * @param integer $posts_per_page Number of items per page.
     *
     * @return void
     */
    private function setPagination($total_items, $posts_per_page)
    {
        $this->set_pagination_args(array(
            'total_items' => $total_items,
            'total_pages' => ceil(($total_items / $posts_per_page)),
            'per_page'    => $posts_per_page,
        ));
    }

    /**
     * Setting the items
     *
     * @return void
     */
    private function parseItems()
    {
        if (is_array($this->items) && count($this->items) > 0) {
            if (!empty($this->search_string)) {
                $this->doSearch();
            }

            $this->setPagination(count($this->items), $this->per_page);

            $this->sortItems();
            $this->paginateItems();
        }
    }

    /**
     * Search through the items
     *
     * @return void
     */
    private function doSearch()
    {
        $results = array();

        foreach ($this->items as $item) {
            foreach ($item as $value) {
                if (stristr($value, $this->search_string) !== false) {
                    $results[] = $item;
                    continue;
                }
            }
        }

        $this->items = $results;
    }

    /**
     * Running the pagination
     *
     * @return void
     */
    private function paginateItems()
    {
        $slice_start = ($this->current_page - 1);
        if ($slice_start < 0) {
            $slice_start = 0;
        }
        // Add pagination
        $this->items = array_slice($this->items, ($slice_start * $this->per_page), $this->per_page);
    }

    /**
     * Sort items
     *
     * @return void
     */
    private function sortItems()
    {
        usort($this->items, array($this, 'doReorder'));
    }

    /**
     * Sort issue
     *
     * @param array $a First data set for comparison.
     * @param array $b Second data set for comparison.
     *
     * @return integer
     */
    private function doReorder($a, $b)
    {
        // orderby default is title
        $orderby = filter_input(INPUT_GET, 'orderby');
        if (!$orderby) {
            $orderby = 'url';
        }

        // order default to asc.
        $order = filter_input(INPUT_GET, 'order');
        if (!$order) {
            $order = 'asc';
        }

        // sort by field
        if (array_key_exists($orderby . '_raw', $a) && array_key_exists($orderby . '_raw', $b)) {
            $orderby = $orderby . '_raw';
        }
        // sort order
        $result = strcmp($a[$orderby], $b[$orderby]);
        return ($order === 'asc') ? $result : (- $result);
    }

    /**
     * Modal box
     *
     * @param string $url URL string.
     *
     * @return string
     */
    private function modalBox($url)
    {
        $current_redirect = false;
        $view_type        = $this->modalBoxType($url, $current_redirect);
        require WPMETASEO_ADDON_PLUGIN_DIR . '/inc/page/google_search_console/wpms-create-redirect.php';
        return $view_type;
    }

    /**
     * Determine which model box type should be rendered
     *
     * @param string $url              URL string.
     * @param string $current_redirect Current redirect by reference.
     *
     * @return string
     */
    private function modalBoxType($url, &$current_redirect)
    {
        if (class_exists('WpmsRedirectManager')) {
            static $redirect_manager;

            if (!$redirect_manager) {
                $redirect_manager = new WpmsRedirectManager();
            }
            $current_redirect = $redirect_manager->getRedirect($url);
            if ($current_redirect) {
                return 'already_exists';
            }

            return 'create';
        }

        return 'no_wpms_addon';
    }

    /**
     * Show hidden fields
     *
     * @param string $platform Platform
     *
     * @return void
     */
    private function showFields($platform)
    {
        echo "<input type='hidden' name='wpms_gsc_nonce' value='" . esc_attr(wp_create_nonce('wpms_gsc_nonce')) . "' />";
        echo '<input id="field_platform" type="hidden" name="platform" value="' . esc_attr($platform) . '" />';
        echo '<input id="field_category" type="hidden" name="category" value="' . esc_attr($this->current_view) . '" />';
    }
}
