<?php
/**
 * Plugin Name: BW Inline Search
 * Plugin URI: https://bowdenworks.com
 * Description: Elegant inline search field that expands from a search icon. Use shortcode [bw_inline_search] or add the widget in Customizer.
 * Version: 1.2.0
 * Author: BowdenWorks
 * Author URI: https://bowdenworks.com
 * License: GPL v2 or later
 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain: bw-inline-search
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

class BW_Inline_Search {

    private static $instance = null;

    public static function get_instance() {
        if ( null === self::$instance ) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function __construct() {
        // Frontend hooks
        add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ) );
        add_action( 'wp_head', array( $this, 'output_scoped_css' ) );
        add_action( 'wp_footer', array( $this, 'output_inline_search_html' ) );
        add_action( 'widgets_init', array( $this, 'register_widget' ) );
        add_shortcode( 'bw_inline_search', array( $this, 'shortcode_output' ) );

        // Admin hooks
        add_action( 'admin_menu', array( $this, 'add_settings_page' ) );
        add_action( 'admin_init', array( $this, 'register_settings' ) );
    }

    /**
     * Get the container CSS selector from settings.
     * Strips dangerous characters to prevent CSS injection.
     */
    private function get_container_selector() {
        $selector = get_option( 'bw_search_container_selector', '.site-header' );
        $selector = preg_replace( '/[;\{\}\\\\]/', '', $selector );
        return trim( $selector );
    }

    /* ========================================
     * Admin Settings
     * ======================================== */

    public function add_settings_page() {
        add_options_page(
            __( 'Search Settings', 'bw-inline-search' ),
            __( 'Search Settings', 'bw-inline-search' ),
            'manage_options',
            'bw-search-settings',
            array( $this, 'render_settings_page' )
        );
    }

    public function register_settings() {
        register_setting( 'bw_search_settings', 'bw_search_container_selector', array(
            'type'              => 'string',
            'default'           => '.site-header',
            'sanitize_callback' => 'sanitize_text_field',
        ) );

        add_settings_section(
            'bw_search_main',
            __( 'Container Settings', 'bw-inline-search' ),
            array( $this, 'render_section_description' ),
            'bw-search-settings'
        );

        add_settings_field(
            'bw_search_container_selector',
            __( 'Container CSS Selector', 'bw-inline-search' ),
            array( $this, 'render_container_field' ),
            'bw-search-settings',
            'bw_search_main'
        );
    }

    public function render_section_description() {
        echo '<p>' . esc_html__( 'Define the CSS selector for the container where the inline search should be active. The plugin styles and behavior will be limited to this container only.', 'bw-inline-search' ) . '</p>';
    }

    public function render_container_field() {
        $value = $this->get_container_selector();
        ?>
        <input type="text" name="bw_search_container_selector" value="<?php echo esc_attr( $value ); ?>" class="regular-text" />
        <p class="description">
            <?php esc_html_e( 'Enter the CSS class or ID of the container element where the search should appear.', 'bw-inline-search' ); ?><br>
            <?php esc_html_e( 'Default: .site-header (Kadence theme)', 'bw-inline-search' ); ?><br>
            <?php esc_html_e( 'Examples: #masthead, .main-header, .site-header, #site-header', 'bw-inline-search' ); ?>
        </p>
        <?php
    }

    public function render_settings_page() {
        if ( ! current_user_can( 'manage_options' ) ) {
            return;
        }
        ?>
        <div class="wrap">
            <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
            <form method="post" action="options.php">
                <?php
                settings_fields( 'bw_search_settings' );
                do_settings_sections( 'bw-search-settings' );
                submit_button();
                ?>
            </form>
        </div>
        <?php
    }

    /* ========================================
     * Frontend Assets
     * ======================================== */

    public function enqueue_assets() {
        // CSS is output dynamically via output_scoped_css() in wp_head
        wp_enqueue_script(
            'bw-inline-search',
            plugin_dir_url( __FILE__ ) . 'js/bw-inline-search.js',
            array(),
            '1.2.0',
            true
        );

        wp_localize_script( 'bw-inline-search', 'bwInlineSearchSettings', array(
            'containerSelector' => $this->get_container_selector(),
        ) );
    }

    /**
     * Output dynamically scoped CSS.
     * All selectors are prefixed with the container selector from settings.
     */
    public function output_scoped_css() {
        $c = $this->get_container_selector();
        $css = "
/* BW Inline Search - Scoped to {$c} */

/* Container */
{$c} .bw-inline-search-container {
    position: relative;
    display: inline-flex;
    align-items: center;
    height: 36px;
}

/* Search icon - always visible when closed */
{$c} .bw-search-icon-wrapper {
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 4px;
    transition: background-color 0.2s ease, opacity 0.2s ease;
    position: relative;
    z-index: 1001;
}

{$c} .bw-search-icon-wrapper:hover {
    background-color: rgba(255, 255, 255, 0.1);
}

{$c} .bw-search-icon-wrapper.bw-hidden {
    opacity: 0;
    pointer-events: none;
    position: absolute;
}

/* The expanding search wrapper */
{$c} .bw-inline-search-wrapper {
    position: absolute;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    align-items: center;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 0.2s ease, visibility 0.2s ease;
    z-index: 1000;
}

{$c} .bw-inline-search-wrapper.bw-active {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
}

/* The search form */
{$c} .bw-inline-search-form {
    display: flex;
    align-items: center;
    background: #545b64;
    border: 1px solid #8c929a;
    border-radius: 4px;
    padding: 0 4px 0 10px;
    margin: 0;
    overflow: hidden;
    box-sizing: border-box;
    height: 36px;
    width: 180px;
    transition: border-color 0.2s ease;
}

{$c} .bw-inline-search-form:focus-within {
    border-color: #4bcac0;
}

/* Search input */
{$c} .bw-inline-search-input {
    border: none !important;
    outline: none !important;
    background: transparent !important;
    font-size: 14px !important;
    line-height: 34px !important;
    height: 34px !important;
    padding: 0 !important;
    margin: 0 !important;
    width: 100%;
    min-width: 0;
    color: #ffffff !important;
    box-shadow: none !important;
    box-sizing: border-box !important;
}

{$c} .bw-inline-search-input::placeholder {
    color: #b0b0b0 !important;
    opacity: 1;
}

{$c} .bw-inline-search-input:focus {
    outline: none !important;
    box-shadow: none !important;
}

/* Submit button */
{$c} .bw-inline-search-submit {
    background: #4bcac0;
    border: none;
    border-radius: 3px;
    padding: 0;
    width: 28px;
    height: 28px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #ffffff;
    transition: background-color 0.2s ease;
    flex-shrink: 0;
}

{$c} .bw-inline-search-submit:hover {
    background: #3aa8a0;
}

{$c} .bw-inline-search-submit svg {
    display: block;
    width: 14px;
    height: 14px;
}

/* Hide original theme search elements inside container */
{$c}.bw-inline-search-active .search-toggle-open-container {
    display: none !important;
}

/* Hide Kadence search drawer globally */
.bw-inline-search-active #search-drawer {
    display: none !important;
}

/* Responsive */
@media (max-width: 1024px) {
    {$c} .bw-inline-search-form {
        width: 160px;
    }
}

@media (max-width: 768px) {
    {$c} .bw-inline-search-wrapper {
        position: fixed;
        right: 15px;
        top: 12px;
        transform: none;
    }
    {$c} .bw-inline-search-form {
        width: 200px;
    }
}

/* Dark theme */
{$c} .bw-inline-search-wrapper.bw-theme-dark .bw-inline-search-form {
    background: #545b64;
    border-color: #8c929a;
}

{$c} .bw-inline-search-wrapper.bw-theme-dark .bw-inline-search-input {
    color: #ffffff !important;
}

{$c} .bw-inline-search-wrapper.bw-theme-dark .bw-inline-search-input::placeholder {
    color: #b0b0b0 !important;
}

/* Light theme */
{$c} .bw-inline-search-wrapper:not(.bw-theme-dark) .bw-inline-search-form {
    background: #ffffff;
    border-color: #d0d0d0;
}

{$c} .bw-inline-search-wrapper:not(.bw-theme-dark) .bw-inline-search-input {
    color: #333333 !important;
}

{$c} .bw-inline-search-wrapper:not(.bw-theme-dark) .bw-inline-search-input::placeholder {
    color: #999999 !important;
}";

        echo '<style id="bw-inline-search-css">' . $css . '</style>' . "\n";
    }

    /* ========================================
     * Shortcode
     * ======================================== */

    /**
     * Shortcode: [bw_inline_search]
     * Attributes:
     *   - placeholder: Custom placeholder text (default: "Search...")
     *   - icon_color: Icon color (default: "currentColor")
     *   - theme: "light" or "dark" (default: "light")
     *   - align: "left", "center", or "right" (default: "left")
     */
    public function shortcode_output( $atts ) {
        $atts = shortcode_atts( array(
            'placeholder' => __( 'Search...', 'bw-inline-search' ),
            'icon_color'  => 'currentColor',
            'theme'       => 'light',
            'align'       => 'left',
        ), $atts, 'bw_inline_search' );

        $theme_class = ( $atts['theme'] === 'dark' ) ? 'bw-theme-dark' : '';
        $align_style = 'text-align: ' . esc_attr( $atts['align'] ) . ';';
        $icon_style  = 'color: ' . esc_attr( $atts['icon_color'] ) . ';';

        ob_start();
        ?>
        <div class="bw-inline-search-container bw-shortcode" style="<?php echo $align_style; ?>">
            <div class="bw-search-icon-wrapper" style="<?php echo $icon_style; ?>" data-bw-search-toggle>
                <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                    <circle cx="11" cy="11" r="8"></circle>
                    <line x1="21" y1="21" x2="16.65" y2="16.65"></line>
                </svg>
            </div>
            <div class="bw-inline-search-wrapper <?php echo esc_attr( $theme_class ); ?>">
                <form role="search" method="get" class="bw-inline-search-form" action="<?php echo esc_url( home_url( '/' ) ); ?>">
                    <input type="search" class="bw-inline-search-input" placeholder="<?php echo esc_attr( $atts['placeholder'] ); ?>" value="" name="s" autocomplete="off" />
                    <button type="submit" class="bw-inline-search-submit" aria-label="<?php esc_attr_e( 'Submit search', 'bw-inline-search' ); ?>">
                        <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                            <circle cx="11" cy="11" r="8"></circle>
                            <line x1="21" y1="21" x2="16.65" y2="16.65"></line>
                        </svg>
                    </button>
                </form>
            </div>
        </div>
        <?php
        return ob_get_clean();
    }

    /**
     * Register the widget
     */
    public function register_widget() {
        register_widget( 'BW_Inline_Search_Widget' );
    }

    public function output_inline_search_html() {
        ?>
        <!-- BW Inline Search Template (for JS auto-replacement of existing search toggles) -->
        <template id="bw-inline-search-template">
            <div class="bw-inline-search-wrapper">
                <form role="search" method="get" class="bw-inline-search-form" action="<?php echo esc_url( home_url( '/' ) ); ?>">
                    <input type="search" class="bw-inline-search-input" placeholder="<?php esc_attr_e( 'Search...', 'bw-inline-search' ); ?>" value="" name="s" autocomplete="off" />
                    <button type="submit" class="bw-inline-search-submit" aria-label="<?php esc_attr_e( 'Submit search', 'bw-inline-search' ); ?>">
                        <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                            <circle cx="11" cy="11" r="8"></circle>
                            <line x1="21" y1="21" x2="16.65" y2="16.65"></line>
                        </svg>
                    </button>
                </form>
            </div>
        </template>
        <?php
    }
}

/**
 * BW Inline Search Widget
 */
class BW_Inline_Search_Widget extends WP_Widget {

    public function __construct() {
        parent::__construct(
            'bw_inline_search_widget',
            __( 'BW Inline Search', 'bw-inline-search' ),
            array(
                'description' => __( 'An elegant inline search that expands from an icon.', 'bw-inline-search' ),
                'classname'   => 'bw-inline-search-widget',
            )
        );
    }

    public function widget( $args, $instance ) {
        $placeholder = ! empty( $instance['placeholder'] ) ? $instance['placeholder'] : __( 'Search...', 'bw-inline-search' );
        $theme       = ! empty( $instance['theme'] ) ? $instance['theme'] : 'light';
        $icon_color  = ! empty( $instance['icon_color'] ) ? $instance['icon_color'] : 'currentColor';

        echo $args['before_widget'];

        $shortcode = sprintf(
            '[bw_inline_search placeholder="%s" theme="%s" icon_color="%s"]',
            esc_attr( $placeholder ),
            esc_attr( $theme ),
            esc_attr( $icon_color )
        );

        echo do_shortcode( $shortcode );

        echo $args['after_widget'];
    }

    public function form( $instance ) {
        $placeholder = ! empty( $instance['placeholder'] ) ? $instance['placeholder'] : __( 'Search...', 'bw-inline-search' );
        $theme       = ! empty( $instance['theme'] ) ? $instance['theme'] : 'light';
        $icon_color  = ! empty( $instance['icon_color'] ) ? $instance['icon_color'] : '';
        ?>
        <p>
            <label for="<?php echo esc_attr( $this->get_field_id( 'placeholder' ) ); ?>"><?php esc_html_e( 'Placeholder Text:', 'bw-inline-search' ); ?></label>
            <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'placeholder' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'placeholder' ) ); ?>" type="text" value="<?php echo esc_attr( $placeholder ); ?>">
        </p>
        <p>
            <label for="<?php echo esc_attr( $this->get_field_id( 'theme' ) ); ?>"><?php esc_html_e( 'Theme:', 'bw-inline-search' ); ?></label>
            <select class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'theme' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'theme' ) ); ?>">
                <option value="light" <?php selected( $theme, 'light' ); ?>><?php esc_html_e( 'Light', 'bw-inline-search' ); ?></option>
                <option value="dark" <?php selected( $theme, 'dark' ); ?>><?php esc_html_e( 'Dark', 'bw-inline-search' ); ?></option>
            </select>
        </p>
        <p>
            <label for="<?php echo esc_attr( $this->get_field_id( 'icon_color' ) ); ?>"><?php esc_html_e( 'Icon Color (CSS color):', 'bw-inline-search' ); ?></label>
            <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'icon_color' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'icon_color' ) ); ?>" type="text" value="<?php echo esc_attr( $icon_color ); ?>" placeholder="e.g. #ffffff or currentColor">
        </p>
        <?php
    }

    public function update( $new_instance, $old_instance ) {
        $instance                = array();
        $instance['placeholder'] = ( ! empty( $new_instance['placeholder'] ) ) ? sanitize_text_field( $new_instance['placeholder'] ) : '';
        $instance['theme']       = ( ! empty( $new_instance['theme'] ) ) ? sanitize_text_field( $new_instance['theme'] ) : 'light';
        $instance['icon_color']  = ( ! empty( $new_instance['icon_color'] ) ) ? sanitize_text_field( $new_instance['icon_color'] ) : '';
        return $instance;
    }
}

// Initialize the plugin
BW_Inline_Search::get_instance();
