<?php
/**
 * DigiFly Search Class
 */

// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

final class Digifly_Search {

    /**
     * Holds the instance
     *
     * Ensures that only one instance of Digifly_Search exists in memory at any one
     * time and it also prevents needing to define globals all over the place.
     *
     * TL;DR This is a static property that holds the singleton instance.
     *
     * @var object
     * @static
     * @since 1.0.3
     */
    private static $instance;

    /**
     * Main Digifly_Search Instance
     *
     * Insures that only one instance of Digifly_Search exists in memory at any one
     * time. Also prevents needing to define globals all over the place.
     *
     * @since 1.0.3
     * @static var array $instance
     * @return The one true Digifly_Search
     */
    public static function instance() {

        if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Digifly_Search ) ) {
            self::$instance = new self;
            self::$instance->hooks();
        }

        return self::$instance;
    }

    /**
     * Constructor Function
     *
     * @since 1.0.3
     *
     * @access private
     */
	private function __construct() {
        self::$instance = $this;
	}

    /**
     * Setup the default hooks and actions
     *
     * @since 1.0.3
     *
     * @return void
     */
    private function hooks() {
        add_action( 'template_redirect', array( $this, 'secondary_navigation_search' ), 20 );
        add_filter( 'wp_nav_menu_items', array( $this, 'mobile_menu_search' ), 20, 2 );
        add_filter( 'digifly_show_sidebar', array( $this, 'hide_sidebar' ) );
    }

    /**
     * Load the search form in the mobile menu.
     *
     * @since 1.0.3
     * @param string $items The HTML list content for the menu items.
     * @param object $args An object containing wp_nav_menu() arguments.
     *
     * @return string $items The HTML list content for the menu items.
     */
    public function mobile_menu_search( $items, $args ) {

        if ( true !== $this->show_header_search() ) {
            return $items;
        }

        if ( 'mobile-menu' === $args->menu_id ) {
            add_filter( 'get_search_form', array( $this, 'search_form' ) );
            $items = '<li class="menu-item menu-item-search">' . get_search_form( false ) . '</li>' . $items;
            remove_filter( 'get_search_form', array( $this, 'search_form' ) );
        }

        return $items;

    }

    /**
     * Load the search form inside the secondary menu.
     *
     * @since 1.0.3
     */
    public function digifly_search_form() {

        if ( true !== $this->show_header_search() ) {
            return;
        }

        add_filter( 'get_search_form', array( $this, 'search_form' ) );
        get_search_form();
        remove_filter( 'get_search_form', array( $this, 'search_form' ) );
    }

    /**
     * Show a unique search form for searching downloads.
     *
     * @since 1.0.3
     * @param string $form The search form HTML output.
     *
     * @return string $form The search form HTML output.
     */
    public function search_form( $form ) {

        // Return the standard search form if the "Restrict Header Search To Products" option is not enabled.
        if ( true !== self::restrict_header_search() ) {
            return $form;
        }

        ob_start();

        $unique_id   = esc_attr( uniqid( 'search-form-' ) );
        $search_text = apply_filters( 'digifly_search_products_text', esc_attr_x( 'Search products', 'placeholder', 'digifly' ) );
        ?>
        <form role="search" method="get" class="search-form" action="<?php echo esc_url( home_url( '/' ) ); ?>">
            <label for="<?php echo $unique_id; ?>">
                <span class="screen-reader-text"><?php echo _x( 'Search products:', 'label', 'digifly' ); ?></span>
                <input type="search" id="<?php echo $unique_id; ?>" class="search-field" placeholder="<?php echo $search_text; ?>" value="<?php echo get_search_query(); ?>" name="s" />
            </label>

            <?php if ( apply_filters( 'digifly_show_search_button', true ) ) : ?>
            <button type="submit" class="search-submit"><span class="screen-reader-text"><?php echo _x( 'Search', 'submit button', 'digifly' ); ?></span><?php echo self::search_icon(); ?></button>
            <?php endif; ?>

            <?php
            /**
             * Search products
             */
            ?>
            <?php if ( class_exists( 'woocommerce' ) ) : ?>
                <input type="hidden" name="post_type" value="product" />
            <?php endif; ?>            
            <?php
            /**
             * Search downloads
             */
            ?>
            <?php if ( class_exists( 'Easy_Digital_Downloads' ) ) : ?>
                <input type="hidden" name="post_type" value="download" />
            <?php endif; ?>            

        </form>

        <?php

        $form = ob_get_contents();
        ob_end_clean();

        return $form;

    }

    /**
     * Display the header search in the secondary menu.
     *
     * @since 1.0.3
     */
    public function secondary_navigation_search() {

        // Load the header search.
        if ( true === $this->show_header_search() ) {
            add_action( 'digifly_secondary_menu', array( $this, 'digifly_search_form' ) );
        }
    
    }

    /**
     * Hide the sidebar on the search results page, if downloads are being displayed.
     *
     * @param boolean $return Whether to hide the sidebar or not.
     * @since 1.0.3
     *
     * @return boolean $return Whether to hide the sidebar or not.
     */
    public function hide_sidebar( $return ) {

        if ( digifly_is_edd_active() && self::is_product_search_results() ) {
            $return = false;
        }

        return $return;

    }

    /**
     * Determine if we're searching products (downloads) only.
     *
     * @since 1.0.3
     *
     * @return boolean $return True if searching products, false otherwise.
     */
    public static function is_product_search_results() {

        $return = false;

        if ( isset( $_GET['post_type'] ) && 'download' === $_GET['post_type'] && 'product' === $_GET['post_type'] ) {
            $return = true;
        }

        return $return;
    }

    /**
     * The search icon displayed all search forms.
     *
     * @since 1.0.3
     *
     * @return string $content The HTML of the SVG
     */
    public static function search_icon() {

        ob_start();
    ?>
        <svg width="16" height="16" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:10;">
            <g>
                <circle cx="6.607" cy="6.607" r="5.201" style="fill:none;stroke-width:2px;"/>
                <path d="M10.284,10.284L14.408,14.408" style="fill:none;stroke-width:2px;stroke-linecap:round;"/>
            </g>
        </svg>
    <?php

        $html = apply_filters( 'digifly_search_icon', ob_get_contents() );
        ob_end_clean();

        return $html;

    }

    /**
     * Whether or not the header search is enabled.
     *
     * @since 1.0.3
     *
     * @return boolean $show_header_search True if the header search is enabled, false otherwise.
     */
    public function show_header_search() {

        $theme_options      = get_theme_mod( 'theme_options' );
        $show_header_search = isset( $theme_options['header_search'] ) && true === $theme_options['header_search'] ? true : false;

        /**
         * Whether or not the header search should be shown.
         *
         * @param boolean $show_header_search True if the header search is enabled, false otherwise.
         * @since 1.0.3
         */
        return apply_filters( 'digifly_show_header_search', $show_header_search );
        
    }

    /**
     * Restrict header search
     * Restricts the header search to only search products (downloads).
     *
     * @since 1.0.3
     *
     * @return boolean $restrict_header_search True if restrict header search is enabled, false otherwise.
     */
     public static function restrict_header_search() {

        $edd_theme_options      = get_theme_mod( 'easy_digital_downloads' );
        $restrict_header_search = isset( $edd_theme_options['restrict_header_search'] ) && true === $edd_theme_options['restrict_header_search'] ? true : false;

        /**
         * Filters the restrict header search option.
         *
         * @param boolean $restrict_header_search True if restricted search is enabled, false otherwise.
         * @since 1.0.3
         */
        return apply_filters( 'digifly_edd_restrict_header_search', $restrict_header_search );

    }

}

/**
 * The main function responsible for returning the one true Digifly_Search instance to functions everywhere.
 *
 * Use this function like you would a global variable, except without needing to declare the global.
 *
 * Example: <?php $digifly_search = digifly_search(); ?>
 *
 * @since 1.0.3
 * @return object The one true Digifly_Search Instance.
 */
function digifly_search() {
    return Digifly_Search::instance();
}

digifly_search();
