<?php

/*
 * *************************************************
 * Copyright (C) 2021 Earworks.                    *
 * Codeigniter Project Template Modification       *
 * Please contact our email for more information : *
 * contact@earworks.co.id                          *
 * *************************************************
 */
defined('BASEPATH') OR exit('No direct script access allowed');

/**
 * Description of MY_Pagination
 *
 * @author Andhy Taslin <andhy@earworks.co.id>
 * @since 1.0
 */
class MY_Pagination extends CI_Pagination {

    /**
     * Disabled first tag open.
     * Please allow us to decide how this link should be appear
     * 
     * @var string 
     */
    protected $first_tag_open_disabled = null;

    /**
     * Disabled first tag close.
     * Please allow us to decide how this link should be appear
     * 
     * @var string
     */
    protected $first_tag_close_disabled = null;

    /**
     * Disabled last tag open.
     * Please allow us to decide how this link should be appear
     * 
     * @var string
     */
    protected $last_tag_open_disabled = null;

    /**
     * Disabled last tag close.
     * Please allow us to decide how this link should be appear
     * 
     * @var string
     */
    protected $last_tag_close_disabled = null;

    /**
     * Disabled previous tag open.
     * Please allow us to decide how this link should be appear
     * 
     * @var string
     */
    protected $prev_tag_open_disabled = null;

    /**
     * Disabled previous tag close.
     * Please allow us to decide how this link should be appear
     * 
     * @var string
     */
    protected $prev_tag_close_disabled = null;

    /**
     * Disabled next tag open.
     * Please allow us to decide how this link should be appear
     * 
     * @var string
     */
    protected $next_tag_open_disabled = null;

    /**
     * Disabled next tag close.
     * Please allow us to decide how this link should be appear
     * 
     * @var string
     */
    protected $next_tag_close_disabled = null;

    /**
     * Override full parent method.
     * 
     * Generate the pagination links
     * 
     * @return string
     */
    public function create_links() {
        // If our item count or per-page total is zero there is no need to continue.
        // Note: DO NOT change the operator to === here!
        if ($this->total_rows == 0 OR $this->per_page == 0) {
            return '';
        }

        // Calculate the total number of pages
        $num_pages = (int) ceil($this->total_rows / $this->per_page);

        // Is there only one page? Hm... nothing more to do here then.
        if ($num_pages === 1) {
            return '';
        }

        // Check the user defined number of links.
        $this->num_links = (int) $this->num_links;

        if ($this->num_links < 0) {
            show_error('Your number of links must be a non-negative number.');
        }

        // Keep any existing query string items.
        // Note: Has nothing to do with any other query string option.
        if ($this->reuse_query_string === TRUE) {
            $get = $this->CI->input->get();

            // Unset the control, method, old-school routing options
            unset($get['c'], $get['m'], $get[$this->query_string_segment]);
        } else {
            $get = array();
        }

        // Put together our base and first URLs.
        // Note: DO NOT append to the properties as that would break successive calls
        $base_url = trim($this->base_url);
        $first_url = $this->first_url;

        $query_string = '';
        $query_string_sep = (strpos($base_url, '?') === FALSE) ? '?' : '&amp;';

        // Are we using query strings?
        if ($this->page_query_string === TRUE) {
            // If a custom first_url hasn't been specified, we'll create one from
            // the base_url, but without the page item.
            if ($first_url === '') {
                $first_url = $base_url;

                // If we saved any GET items earlier, make sure they're appended.
                if (!empty($get)) {
                    $first_url .= $query_string_sep . http_build_query($get);
                }
            }

            // Add the page segment to the end of the query string, where the
            // page number will be appended.
            $base_url .= $query_string_sep . http_build_query(array_merge($get, array($this->query_string_segment => '')));
        } else {
            // Standard segment mode.
            // Generate our saved query string to append later after the page number.
            if (!empty($get)) {
                $query_string = $query_string_sep . http_build_query($get);
                $this->suffix .= $query_string;
            }

            // Does the base_url have the query string in it?
            // If we're supposed to save it, remove it so we can append it later.
            if ($this->reuse_query_string === TRUE && ($base_query_pos = strpos($base_url, '?')) !== FALSE) {
                $base_url = substr($base_url, 0, $base_query_pos);
            }

            if ($first_url === '') {
                $first_url = $base_url . $query_string;
            }

            $base_url = rtrim($base_url, '/') . '/';
        }

        // Determine the current page number.
        $base_page = ($this->use_page_numbers) ? 1 : 0;

        // Are we using query strings?
        if ($this->page_query_string === TRUE) {
            $this->cur_page = $this->CI->input->get($this->query_string_segment);
        } elseif (empty($this->cur_page)) {
            // Default to the last segment number if one hasn't been defined.
            if ($this->uri_segment === 0) {
                $this->uri_segment = count($this->CI->uri->segment_array());
            }

            $this->cur_page = $this->CI->uri->segment($this->uri_segment);

            // Remove any specified prefix/suffix from the segment.
            if ($this->prefix !== '' OR $this->suffix !== '') {
                $this->cur_page = str_replace(array($this->prefix, $this->suffix), '', $this->cur_page);
            }
        } else {
            $this->cur_page = (string) $this->cur_page;
        }

        // If something isn't quite right, back to the default base page.
        if (!ctype_digit($this->cur_page) OR ($this->use_page_numbers && (int) $this->cur_page === 0)) {
            $this->cur_page = $base_page;
        } else {
            // Make sure we're using integers for comparisons later.
            $this->cur_page = (int) $this->cur_page;
        }

        // Is the page number beyond the result range?
        // If so, we show the last page.
        if ($this->use_page_numbers) {
            if ($this->cur_page > $num_pages) {
                $this->cur_page = $num_pages;
            }
        } elseif ($this->cur_page > $this->total_rows) {
            $this->cur_page = ($num_pages - 1) * $this->per_page;
        }

        $uri_page_number = $this->cur_page;

        // If we're using offset instead of page numbers, convert it
        // to a page number, so we can generate the surrounding number links.
        if (!$this->use_page_numbers) {
            $this->cur_page = (int) floor(($this->cur_page / $this->per_page) + 1);
        }

        // Calculate the start and end numbers. These determine
        // which number to start and end the digit links with.
        $start = (($this->cur_page - $this->num_links) > 0) ? $this->cur_page - ($this->num_links - 1) : 1;
        $end = (($this->cur_page + $this->num_links) < $num_pages) ? $this->cur_page + $this->num_links : $num_pages;

        // And here we go...
        $output = '';

        // Render the "First" link.
        if ($this->first_link !== FALSE && $this->cur_page > 1) {
            // Take the general parameters, and squeeze this pagination-page attr in for JS frameworks.
            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, 1);

            $output .= $this->first_tag_open . '<a href="' . $first_url . '"' . $attributes . $this->_attr_rel('start') . '>'
                    . $this->first_link . '</a>' . $this->first_tag_close;
        } elseif ($this->first_link !== FALSE && $this->cur_page <= 1) {
            // Take the general parameters, and squeeze this pagination-page attr in for JS frameworks.
            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, 1);

            $output .= $this->first_tag_open_disabled . '<a href="javascript:void(0)"' . $attributes . $this->_attr_rel('start') . '>'
                    . $this->first_link . '</a>' . $this->first_tag_close_disabled;
        }

        // Render the "Previous" link.
        if ($this->prev_link !== FALSE && $this->cur_page !== 1) {
            $i = ($this->use_page_numbers) ? $uri_page_number - 1 : $uri_page_number - $this->per_page;

            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, ($this->cur_page - 1));

            if ($i === $base_page) {
                // First page
                $output .= $this->prev_tag_open . '<a href="' . $first_url . '"' . $attributes . $this->_attr_rel('prev') . '>'
                        . $this->prev_link . '</a>' . $this->prev_tag_close;
            } else {
                $append = $this->prefix . $i . $this->suffix;
                $output .= $this->prev_tag_open . '<a href="' . $base_url . $append . '"' . $attributes . $this->_attr_rel('prev') . '>'
                        . $this->prev_link . '</a>' . $this->prev_tag_close;
            }
        } else {
            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, ($this->cur_page - 1));
            $output .= $this->prev_tag_open_disabled . '<a href="javascript:void(0)"' . $attributes . $this->_attr_rel('prev') . '>'
                    . $this->prev_link . '</a>' . $this->prev_tag_close_disabled;
        }

        // Render the pages
        if ($this->display_pages !== FALSE) {
            // Write the digit links
            for ($loop = $start - 1; $loop <= $end; $loop++) {
                $i = ($this->use_page_numbers) ? $loop : ($loop * $this->per_page) - $this->per_page;

                $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $loop);

                if ($i >= $base_page) {
                    if ($this->cur_page === $loop) {
                        // Current page
                        $output .= $this->cur_tag_open . $loop . $this->cur_tag_close;
                    } elseif ($i === $base_page) {
                        // First page
                        $output .= $this->num_tag_open . '<a href="' . $first_url . '"' . $attributes . $this->_attr_rel('start') . '>'
                                . $loop . '</a>' . $this->num_tag_close;
                    } else {
                        $append = $this->prefix . $i . $this->suffix;
                        $output .= $this->num_tag_open . '<a href="' . $base_url . $append . '"' . $attributes . '>'
                                . $loop . '</a>' . $this->num_tag_close;
                    }
                }
            }
        }

        // Render the "next" link
        if ($this->next_link !== FALSE && $this->cur_page < $num_pages) {
            $i = ($this->use_page_numbers) ? $this->cur_page + 1 : $this->cur_page * $this->per_page;

            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $this->cur_page + 1);

            $output .= $this->next_tag_open . '<a href="' . $base_url . $this->prefix . $i . $this->suffix . '"' . $attributes
                    . $this->_attr_rel('next') . '>' . $this->next_link . '</a>' . $this->next_tag_close;
        } else {
            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $this->cur_page + 1);

            $output .= $this->next_tag_open_disabled . '<a href="javascript:void(0)"' . $attributes
                    . $this->_attr_rel('next') . '>' . $this->next_link . '</a>' . $this->next_tag_close_disabled;
        }

        // Render the "Last" link
        if ($this->last_link !== FALSE && $this->cur_page < $num_pages) {
            $i = ($this->use_page_numbers) ? $num_pages : ($num_pages * $this->per_page) - $this->per_page;

            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $num_pages);

            $output .= $this->last_tag_open . '<a href="' . $base_url . $this->prefix . $i . $this->suffix . '"' . $attributes . '>'
                    . $this->last_link . '</a>' . $this->last_tag_close;
        } else {

            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $num_pages);

            $output .= $this->last_tag_open_disabled . '<a href="javascript:void(0)"' . $attributes . '>'
                    . $this->last_link . '</a>' . $this->last_tag_close_disabled;
        }

        // Kill double slashes. Note: Sometimes we can end up with a double slash
        // in the penultimate link so we'll kill all double slashes.
        $output = preg_replace('#([^:"])//+#', '\\1/', $output);
        // Add the wrapper HTML if exists
        return $this->full_tag_open . $output . $this->full_tag_close;
    }

    /**
     * Override full parent method.
     * 
     * Generate the pagination links
     * 
     * @return string
     */
    public function create_ajax_links() {
        // If our item count or per-page total is zero there is no need to continue.
        // Note: DO NOT change the operator to === here!
        if ($this->total_rows == 0 OR $this->per_page == 0) {
            return '';
        }

        // Calculate the total number of pages
        $num_pages = (int) ceil($this->total_rows / $this->per_page);

        // Is there only one page? Hm... nothing more to do here then.
        if ($num_pages === 1) {
            return '';
        }

        // Check the user defined number of links.
        $this->num_links = (int) $this->num_links;

        if ($this->num_links < 0) {
            show_error('Your number of links must be a non-negative number.');
        }

        // Keep any existing query string items.
        // Note: Has nothing to do with any other query string option.
        if ($this->reuse_query_string === TRUE) {
            $get = $this->CI->input->get();

            // Unset the control, method, old-school routing options
            unset($get['c'], $get['m'], $get[$this->query_string_segment]);
        } else {
            $get = array();
        }

        // Put together our base and first URLs.
        // Note: DO NOT append to the properties as that would break successive calls
        $base_url = trim($this->base_url);
        $first_url = $this->first_url;

        $query_string = '';
        $query_string_sep = (strpos($base_url, '?') === FALSE) ? '?' : '&amp;';

        // Are we using query strings?
        if ($this->page_query_string === TRUE) {
            // If a custom first_url hasn't been specified, we'll create one from
            // the base_url, but without the page item.
            if ($first_url === '') {
                $first_url = $base_url;

                // If we saved any GET items earlier, make sure they're appended.
                if (!empty($get)) {
                    $first_url .= $query_string_sep . http_build_query($get);
                }
            }

            // Add the page segment to the end of the query string, where the
            // page number will be appended.
            $base_url .= $query_string_sep . http_build_query(array_merge($get, array($this->query_string_segment => '')));
        } else {
            // Standard segment mode.
            // Generate our saved query string to append later after the page number.
            if (!empty($get)) {
                $query_string = $query_string_sep . http_build_query($get);
                $this->suffix .= $query_string;
            }

            // Does the base_url have the query string in it?
            // If we're supposed to save it, remove it so we can append it later.
            if ($this->reuse_query_string === TRUE && ($base_query_pos = strpos($base_url, '?')) !== FALSE) {
                $base_url = substr($base_url, 0, $base_query_pos);
            }

            if ($first_url === '') {
                $first_url = $base_url . $query_string;
            }

            $base_url = rtrim($base_url, '/') . '/';
        }

        // Determine the current page number.
        $base_page = ($this->use_page_numbers) ? 1 : 0;

        // Are we using query strings?
        if ($this->page_query_string === TRUE) {
            $this->cur_page = $this->CI->input->get($this->query_string_segment);
        } elseif (empty($this->cur_page)) {
            // Default to the last segment number if one hasn't been defined.
            if ($this->uri_segment === 0) {
                $this->uri_segment = count($this->CI->uri->segment_array());
            }

            $this->cur_page = $this->CI->uri->segment($this->uri_segment);

            // Remove any specified prefix/suffix from the segment.
            if ($this->prefix !== '' OR $this->suffix !== '') {
                $this->cur_page = str_replace(array($this->prefix, $this->suffix), '', $this->cur_page);
            }
        } else {
            $this->cur_page = (string) $this->cur_page;
        }

        // If something isn't quite right, back to the default base page.
        if (!ctype_digit($this->cur_page) OR ($this->use_page_numbers && (int) $this->cur_page === 0)) {
            $this->cur_page = $base_page;
        } else {
            // Make sure we're using integers for comparisons later.
            $this->cur_page = (int) $this->cur_page;
        }

        // Is the page number beyond the result range?
        // If so, we show the last page.
        if ($this->use_page_numbers) {
            if ($this->cur_page > $num_pages) {
                $this->cur_page = $num_pages;
            }
        } elseif ($this->cur_page > $this->total_rows) {
            $this->cur_page = ($num_pages - 1) * $this->per_page;
        }

        $uri_page_number = $this->cur_page;

        // If we're using offset instead of page numbers, convert it
        // to a page number, so we can generate the surrounding number links.
        if (!$this->use_page_numbers) {
            $this->cur_page = (int) floor(($this->cur_page / $this->per_page) + 1);
        }

        // Calculate the start and end numbers. These determine
        // which number to start and end the digit links with.
        $start = (($this->cur_page - $this->num_links) > 0) ? $this->cur_page - ($this->num_links - 1) : 1;
        $end = (($this->cur_page + $this->num_links) < $num_pages) ? $this->cur_page + $this->num_links : $num_pages;

        // And here we go...
        $output = '';

        // Render the "First" link.
        if ($this->first_link !== FALSE && $this->cur_page > 1) {
            // Take the general parameters, and squeeze this pagination-page attr in for JS frameworks.
            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, 1);

            $output .= $this->first_tag_open . '<a href="javascript:void(0)" onclick=" script.ajaxlinkbtn(this, null, false);" data-url="' . $first_url . '"' . $attributes . $this->_attr_rel('start') . '>'
                    . $this->first_link . '</a>' . $this->first_tag_close;
        } elseif ($this->first_link !== FALSE && $this->cur_page <= 1) {
            // Take the general parameters, and squeeze this pagination-page attr in for JS frameworks.
            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, 1);

            $output .= $this->first_tag_open_disabled . '<a href="javascript:void(0)"' . $attributes . $this->_attr_rel('start') . '>'
                    . $this->first_link . '</a>' . $this->first_tag_close_disabled;
        }

        // Render the "Previous" link.
        if ($this->prev_link !== FALSE && $this->cur_page !== 1) {
            $i = ($this->use_page_numbers) ? $uri_page_number - 1 : $uri_page_number - $this->per_page;

            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, ($this->cur_page - 1));

            if ($i === $base_page) {
                // First page
                $output .= $this->prev_tag_open . '<a href="javascript:void(0)" onclick=" script.ajaxlinkbtn(this, null, false);" data-url="' . $first_url . '"' . $attributes . $this->_attr_rel('prev') . '>'
                        . $this->prev_link . '</a>' . $this->prev_tag_close;
            } else {
                $append = $this->prefix . $i . $this->suffix;
                $output .= $this->prev_tag_open . '<a href="javascript:void(0)" onclick=" script.ajaxlinkbtn(this, null, false);" data-url="' . $base_url . $append . '"' . $attributes . $this->_attr_rel('prev') . '>'
                        . $this->prev_link . '</a>' . $this->prev_tag_close;
            }
        } else {
            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, ($this->cur_page - 1));
            $output .= $this->prev_tag_open_disabled . '<a href="javascript:void(0)"' . $attributes . $this->_attr_rel('prev') . '>'
                    . $this->prev_link . '</a>' . $this->prev_tag_close_disabled;
        }

        // Render the pages
        if ($this->display_pages !== FALSE) {
            // Write the digit links
            for ($loop = $start - 1; $loop <= $end; $loop++) {
                $i = ($this->use_page_numbers) ? $loop : ($loop * $this->per_page) - $this->per_page;

                $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $loop);

                if ($i >= $base_page) {
                    if ($this->cur_page === $loop) {
                        // Current page
                        $output .= $this->cur_tag_open . $loop . $this->cur_tag_close;
                    } elseif ($i === $base_page) {
                        // First page
                        $output .= $this->num_tag_open . '<a href="javascript:void(0)" onclick=" script.ajaxlinkbtn(this, null, false);" data-url="' . $first_url . '"' . $attributes . $this->_attr_rel('start') . '>'
                                . $loop . '</a>' . $this->num_tag_close;
                    } else {
                        $append = $this->prefix . $i . $this->suffix;
                        $output .= $this->num_tag_open . '<a href="javascript:void(0)" onclick=" script.ajaxlinkbtn(this, null, false);" data-url="' . $base_url . $append . '"' . $attributes . '>'
                                . $loop . '</a>' . $this->num_tag_close;
                    }
                }
            }
        }

        // Render the "next" link
        if ($this->next_link !== FALSE && $this->cur_page < $num_pages) {
            $i = ($this->use_page_numbers) ? $this->cur_page + 1 : $this->cur_page * $this->per_page;

            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $this->cur_page + 1);

            $output .= $this->next_tag_open . '<a href="javascript:void(0)" onclick=" script.ajaxlinkbtn(this, null, false);" data-url="' . $base_url . $this->prefix . $i . $this->suffix . '"' . $attributes
                    . $this->_attr_rel('next') . '>' . $this->next_link . '</a>' . $this->next_tag_close;
        } else {
            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $this->cur_page + 1);

            $output .= $this->next_tag_open_disabled . '<a href="javascript:void(0)"' . $attributes
                    . $this->_attr_rel('next') . '>' . $this->next_link . '</a>' . $this->next_tag_close_disabled;
        }

        // Render the "Last" link
        if ($this->last_link !== FALSE && $this->cur_page < $num_pages) {
            $i = ($this->use_page_numbers) ? $num_pages : ($num_pages * $this->per_page) - $this->per_page;

            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $num_pages);

            $output .= $this->last_tag_open . '<a href="javascript:void(0)" onclick=" script.ajaxlinkbtn(this, null, false);" data-url="' . $base_url . $this->prefix . $i . $this->suffix . '"' . $attributes . '>'
                    . $this->last_link . '</a>' . $this->last_tag_close;
        } else {

            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $num_pages);

            $output .= $this->last_tag_open_disabled . '<a href="javascript:void(0)"' . $attributes . '>'
                    . $this->last_link . '</a>' . $this->last_tag_close_disabled;
        }

        // Kill double slashes. Note: Sometimes we can end up with a double slash
        // in the penultimate link so we'll kill all double slashes.
        $output = preg_replace('#([^:"])//+#', '\\1/', $output);
        // Add the wrapper HTML if exists
        return $this->full_tag_open . $output . $this->full_tag_close;
    }

    /**
     * Override full parent method.
     * 
     * Generate the pagination links
     * 
     * @return string
     */
    public function create_api_links() {
        // If our item count or per-page total is zero there is no need to continue.
        // Note: DO NOT change the operator to === here!
        if ($this->total_rows == 0 OR $this->per_page == 0) {
            return [];
        }

        // Calculate the total number of pages
        $num_pages = (int) ceil($this->total_rows / $this->per_page);

        // Is there only one page? Hm... nothing more to do here then.
        if ($num_pages === 1) {
            return [];
        }


        // Check the user defined number of links.
        $this->num_links = (int) $this->num_links;

        if ($this->num_links < 0) {
            show_error('Your number of links must be a non-negative number.');
        }

        // Keep any existing query string items.
        // Note: Has nothing to do with any other query string option.
        if ($this->reuse_query_string === TRUE) {
            $get = $this->CI->input->get();

            // Unset the control, method, old-school routing options
            unset($get['c'], $get['m'], $get[$this->query_string_segment]);
        } else {
            $get = array();
        }

        // Put together our base and first URLs.
        // Note: DO NOT append to the properties as that would break successive calls
        $base_url = trim($this->base_url);
        $first_url = $this->first_url;

        $query_string = '';
        $query_string_sep = (strpos($base_url, '?') === FALSE) ? '?' : '&amp;';

        // Are we using query strings?
        if ($this->page_query_string === TRUE) {
            // If a custom first_url hasn't been specified, we'll create one from
            // the base_url, but without the page item.
            if ($first_url === '') {
                $first_url = $base_url;

                // If we saved any GET items earlier, make sure they're appended.
                if (!empty($get)) {
                    $first_url .= $query_string_sep . http_build_query($get);
                }
            }

            // Add the page segment to the end of the query string, where the
            // page number will be appended.
            $base_url .= $query_string_sep . http_build_query(array_merge($get, array($this->query_string_segment => '')));
        } else {
            // Standard segment mode.
            // Generate our saved query string to append later after the page number.
            if (!empty($get)) {
                $query_string = $query_string_sep . http_build_query($get);
                $this->suffix .= $query_string;
            }

            // Does the base_url have the query string in it?
            // If we're supposed to save it, remove it so we can append it later.
            if ($this->reuse_query_string === TRUE && ($base_query_pos = strpos($base_url, '?')) !== FALSE) {
                $base_url = substr($base_url, 0, $base_query_pos);
            }

            if ($first_url === '') {
                $first_url = $base_url . $query_string;
            }

            $base_url = rtrim($base_url, '/') . '/';
        }

        // Determine the current page number.
        $base_page = ($this->use_page_numbers) ? 1 : 0;

        // Are we using query strings?
        if ($this->page_query_string === TRUE) {
            $this->cur_page = $this->CI->input->get($this->query_string_segment);
        } elseif (empty($this->cur_page)) {
            // Default to the last segment number if one hasn't been defined.
            if ($this->uri_segment === 0) {
                $this->uri_segment = count($this->CI->uri->segment_array());
            }

            $this->cur_page = $this->CI->uri->segment($this->uri_segment);

            // Remove any specified prefix/suffix from the segment.
            if ($this->prefix !== '' OR $this->suffix !== '') {
                $this->cur_page = str_replace(array($this->prefix, $this->suffix), '', $this->cur_page);
            }
        } else {
            $this->cur_page = (string) $this->cur_page;
        }

        // If something isn't quite right, back to the default base page.
        if (!ctype_digit($this->cur_page) OR ($this->use_page_numbers && (int) $this->cur_page === 0)) {
            $this->cur_page = $base_page;
        } else {
            // Make sure we're using integers for comparisons later.
            $this->cur_page = (int) $this->cur_page;
        }

        // Is the page number beyond the result range?
        // If so, we show the last page.
        if ($this->use_page_numbers) {
            if ($this->cur_page > $num_pages) {
                $this->cur_page = $num_pages;
            }
        } elseif ($this->cur_page > $this->total_rows) {
            $this->cur_page = ($num_pages - 1) * $this->per_page;
        }

        $uri_page_number = $this->cur_page;

        // If we're using offset instead of page numbers, convert it
        // to a page number, so we can generate the surrounding number links.
        if (!$this->use_page_numbers) {
            $this->cur_page = (int) floor(($this->cur_page / $this->per_page) + 1);
        }

        // Calculate the start and end numbers. These determine
        // which number to start and end the digit links with.
        $start = (($this->cur_page - $this->num_links) > 0) ? $this->cur_page - ($this->num_links - 1) : 1;
        $end = (($this->cur_page + $this->num_links) < $num_pages) ? $this->cur_page + $this->num_links : $num_pages;

        // And here we go...
        $output = [];

        // Render the "First" link.
        if ($this->first_link !== FALSE && $this->cur_page > 1) {
            // Take the general parameters, and squeeze this pagination-page attr in for JS frameworks.
            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, 1);

            $output[] = [
                'link' => $this->first_link,
                'url' => $first_url
            ];
        } elseif ($this->first_link !== FALSE && $this->cur_page <= 1) {
            // Take the general parameters, and squeeze this pagination-page attr in for JS frameworks.
            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, 1);

            $output[] = [
                'link' => $this->first_link,
                'url' => null
            ];
        }

        // Render the "Previous" link.
        if ($this->prev_link !== FALSE && $this->cur_page !== 1) {
            $i = ($this->use_page_numbers) ? $uri_page_number - 1 : $uri_page_number - $this->per_page;

            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, ($this->cur_page - 1));

            if ($i === $base_page) {
                // First page
                $output[] = [
                    'link' => $this->prev_link,
                    'url' => $first_url
                ];
            } else {
                $append = $this->prefix . $i . $this->suffix;
                $output[] = [
                    'link' => $this->prev_link,
                    'url' => $base_url . $append
                ];
            }
        } else {
            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, ($this->cur_page - 1));
            $output[] = [
                'link' => $this->prev_link,
                'url' => null
            ];
        }

        // Render the pages
        if ($this->display_pages !== FALSE) {
            // Write the digit links
            for ($loop = $start - 1; $loop <= $end; $loop++) {
                $i = ($this->use_page_numbers) ? $loop : ($loop * $this->per_page) - $this->per_page;

                $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $loop);

                if ($i >= $base_page) {
                    if ($this->cur_page === $loop) {
                        // Current page
                        $output[] = [
                            'link' => $loop,
                            'url' => null
                        ];
                    } elseif ($i === $base_page) {
                        // First page
                        $output[] = [
                            'link' => $loop,
                            'url' => $first_url
                        ];
                    } else {
                        $append = $this->prefix . $i . $this->suffix;
                        $output[] = [
                            'link' => $loop,
                            'url' => $base_url . $append
                        ];
                    }
                }
            }
        }

        // Render the "next" link
        if ($this->next_link !== FALSE && $this->cur_page < $num_pages) {
            $i = ($this->use_page_numbers) ? $this->cur_page + 1 : $this->cur_page * $this->per_page;

            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $this->cur_page + 1);
            $output[] = [
                'link' => $this->next_link,
                'url' => $base_url . $this->prefix . $i . $this->suffix
            ];
        } else {
            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $this->cur_page + 1);
            $output[] = [
                'link' => $this->next_link,
                'url' => null,
            ];
        }

        // Render the "Last" link
        if ($this->last_link !== FALSE && $this->cur_page < $num_pages) {
            $i = ($this->use_page_numbers) ? $num_pages : ($num_pages * $this->per_page) - $this->per_page;

            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $num_pages);
            $output[] = [
                'link' => $this->last_link,
                'url' => $base_url . $this->prefix . $i . $this->suffix,
            ];
        } else {

            $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $num_pages);
            $output[] = [
                'link' => $this->last_link,
                'url' => null
            ];
        }
        return $output;
    }

    public function create_forms($config = []) {
        $this->CI->load->config('pagination');
        $this->CI->load->helper('form');
        $default_per_page = isset($config['per_page']) ? $config['per_page'] : null;
        $default_keyword = isset($config['keyword']) ? $config['keyword'] : null;
        $default_order = isset($config['order']) ? $config['order'] : null;
        $per_page_option = isset($config['per_page_options']) ? $config['per_page_options'] : $this->CI->config->item('per_page_options');

        $output = form_open('', ['method' => 'GET', 'class' => 'form-inline search-form', 'id' => 'search-form']);
        $output .= '<div class="search">' .
                '   <div class="form-group">' .
                '       <div class="input-group">' .
                '           <div class="input-group-addon">' . lang('view_row') . ':</div>' .
                form_dropdown('show', $per_page_option, $default_per_page, ['class' => 'form-control', 'onchange' => 'script.change_per_page(this)']) .
                '       </div>' .
                '   </div>' .
                '   <div class="form-group">' .
                form_input('keyword', $default_keyword, ['class' => 'form-control', 'placeholder' => lang('search_placeholder')]) .
                '   </div>' .
                '</div>' .
                form_hidden('order', $default_order) .
                '<div class="form-group">' .
                form_submit('submit', 'Search', ['class' => 'btn blue btn-search', 'style' => 'display:none;']) .
                '</div>' .
                form_close();
        return $output;
    }

    public function create_ajax_forms($config = []) {
        $this->CI->load->config('pagination');
        $this->CI->load->helper('form');
        $default_per_page = isset($config['per_page']) ? $config['per_page'] : null;
        $default_keyword = isset($config['keyword']) ? $config['keyword'] : null;
        $default_order = isset($config['order']) ? $config['order'] : null;
        $per_page_option = isset($config['per_page_options']) ? $config['per_page_options'] : $this->CI->config->item('per_page_options');

        $output = form_open('', ['method' => 'GET', 'class' => 'form-inline search-form', 'id' => 'search-form', 'onsubmit' => 'return script.ajaxlinkform(event);']);
        $output .= '<div class="search">' .
                '   <div class="form-group">' .
                '       <div class="input-group">' .
                '           <div class="input-group-addon">' . lang('view_row') . ':</div>' .
                form_dropdown('show', $per_page_option, $default_per_page, ['class' => 'form-control', 'onchange' => 'script.change_per_page(this)']) .
                '       </div>' .
                '   </div>' .
                '   <div class="form-group">' .
                form_input('keyword', $default_keyword, ['class' => 'form-control', 'placeholder' => lang('search_placeholder')]) .
                '   </div>' .
                '</div>' .
                form_hidden('order', $default_order) .
                '<div class="form-group">' .
                form_submit('submit', 'Search', ['class' => 'btn blue btn-search', 'style' => 'display:none;']) .
                '</div>' .
                form_close();
        return $output;
    }

    public function open_form($config = []) {
        $this->CI->load->config('pagination');
        $this->CI->load->helper('form');
        $default_per_page = isset($config['per_page']) ? $config['per_page'] : null;
        $default_keyword = isset($config['keyword']) ? $config['keyword'] : null;
        $default_order = isset($config['order']) ? $config['order'] : null;
        $per_page_option = isset($config['per_page_options']) ? $config['per_page_options'] : $this->CI->config->item('per_page_options');

        $output = form_open('', ['method' => 'GET', 'class' => 'form-inline search-form', 'id' => 'search-form']);
        $output .= '<div class="search">' .
                '   <div class="form-group">' .
                '       <div class="input-group">' .
                '           <div class="input-group-addon">' . lang('view_row') . ':</div>' .
                form_dropdown('show', $per_page_option, $default_per_page, ['class' => 'form-control', 'onchange' => 'script.change_per_page(this)']) .
                '       </div>' .
                '   </div>' .
                '   <div class="form-group">' .
                form_input('keyword', $default_keyword, ['class' => 'form-control', 'placeholder' => lang('search_placeholder')]) .
                '   </div>' .
                '</div>' .
                form_hidden('order', $default_order);
        return $output;
    }

    public function close_form() {
        $this->CI->load->helper('form');
        $output = '<div class="form-group">' .
                form_submit('submit', 'Search', ['class' => 'btn blue', 'style' => 'display:none;']) .
                '</div>' .
                form_close();
        return $output;
    }

    public function check_all_header() {
        $output = '<th style="width:20px;">' .
                '   <div class="mt-checkbox-inline" style="padding:0;">' .
                '       <label class="mt-checkbox mt-checkbox-outline">' .
                '           <input type="checkbox" name="delete_all" value="1" onchange="script.toggle_checkbox(this)" data-target="data-checkbox" id="data-checkbox-all"/>' .
                '           <span></span>' .
                '       </label>' .
                '   </div>' .
                '</th>';
        return $output;
    }

    public function check_all($value = null) {
        $output = '<td style="width:20px;">' .
                '   <div class="mt-checkbox-inline"  style="padding:0;">' .
                '       <label class="mt-checkbox mt-checkbox-outline">' .
                '           <input type="checkbox" name="check_all[]" value="{val}" class="data-checkbox" onclick="script.toggle_checkbox_all(this)" data-target="data-checkbox-all"/>' .
                '           <span></span>' .
                '       </label>' .
                '   </div>' .
                '</td>';
        return strtr($output, [
            '{val}' => $value
        ]);
    }

}
