<?php
/**
 * Plugin Name: MP3 VPlayer
 * Plugin URI: https://wordpress.org/plugins/mp3-vplayer/
 * Description: Sleek MP3 player with shortcode support for single tracks and playlists from any taxonomy
 * Version: 1.0.8
 * Author: Vijeet Deliwala
 * Author URI: https://vijeetdeliwala.com
 * License: GPL v2 or later
 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain: mp3-vplayer
 * Domain Path: /languages
 */

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

/** -------------------------------------------------------------------------
 *  Activation redirect (hook MUST be in the main plugin file scope)
 *  ---------------------------------------------------------------------- */
function mp3_vplayer_on_activate() {
    if ( false === get_option( 'mp3_vplayer_post_types' ) ) {
        add_option( 'mp3_vplayer_post_types', array( 'post', 'page' ) );
    }
    set_transient( 'mp3_vplayer_do_activation_redirect', 1, 30 );
}
register_activation_hook( __FILE__, 'mp3_vplayer_on_activate' );

class MP3_VPlayer {

    /**
     * @var array
     */
    private $post_types = array();

    public function __construct() {
        // WP.org auto-loads translations – no load_plugin_textdomain() call needed.

        // Settings and admin
        add_action( 'admin_menu', array( $this, 'add_settings_page' ) );
        add_action( 'admin_init', array( $this, 'register_settings' ) );
        add_action( 'admin_init', array( $this, 'maybe_redirect_to_settings' ) );
        add_filter(
            'plugin_action_links_' . plugin_basename( __FILE__ ),
            array( $this, 'add_settings_link' )
        );

        // Front-end assets
        add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ) );

        // Admin assets (for meta box uploader JS)
        add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_assets' ) );

        // Shortcode
        add_shortcode( 'mp3_vplayer', array( $this, 'mp3_vplayer_shortcode' ) );

        // Meta boxes
        add_action( 'add_meta_boxes', array( $this, 'add_mp3_meta_box' ) );
        add_action( 'save_post', array( $this, 'save_mp3_meta' ) );

        $this->post_types = get_option(
            'mp3_vplayer_post_types',
            array( 'post', 'page' )
        );
    }

    /** Redirect to settings once after activation */
    public function maybe_redirect_to_settings() {
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        if (
            is_admin()
            && ! defined( 'DOING_AJAX' )
            && ! isset( $_GET['activate-multi'] )
            && get_transient( 'mp3_vplayer_do_activation_redirect' )
        ) {
            delete_transient( 'mp3_vplayer_do_activation_redirect' );
            wp_safe_redirect(
                admin_url( 'options-general.php?page=mp3-vplayer-settings' )
            );
            exit;
        }
    }

    /** Settings link on Plugins list */
    public function add_settings_link( $links ) {
        $settings_link = '<a href="' . esc_url(
            admin_url( 'options-general.php?page=mp3-vplayer-settings' )
        ) . '">' . esc_html__( 'Settings', 'mp3-vplayer' ) . '</a>';

        array_unshift( $links, $settings_link );

        return $links;
    }

    /** Settings page */
    public function add_settings_page() {
        add_options_page(
            __( 'MP3 VPlayer Settings', 'mp3-vplayer' ),
            __( 'MP3 VPlayer', 'mp3-vplayer' ),
            'manage_options',
            'mp3-vplayer-settings',
            array( $this, 'render_settings_page' )
        );
    }

    public function register_settings() {
        register_setting(
            'mp3_vplayer_settings',
            'mp3_vplayer_post_types',
            array(
                'type'              => 'array',
                'sanitize_callback' => array( $this, 'sanitize_post_types' ),
                'default'           => array( 'post', 'page' ),
            )
        );
    }

    public function sanitize_post_types( $val ) {
        if ( ! is_array( $val ) ) {
            return array( 'post', 'page' );
        }

        return array_values(
            array_filter(
                array_map( 'sanitize_key', $val )
            )
        );
    }

    public function render_settings_page() {
        if ( ! current_user_can( 'manage_options' ) ) {
            return;
        }

        $post_types          = get_post_types(
            array( 'public' => true ),
            'objects'
        );
        $selected_post_types = get_option(
            'mp3_vplayer_post_types',
            array( 'post', 'page' )
        );
        ?>
        <div class="wrap">
            <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
            <form method="post" action="options.php">
                <?php settings_fields( 'mp3_vplayer_settings' ); ?>
                <table class="form-table" role="presentation">
                    <tr>
                        <th><?php esc_html_e( 'Enable MP3 Meta Box For:', 'mp3-vplayer' ); ?></th>
                        <td>
                            <?php foreach ( $post_types as $pt ) : ?>
                                <label style="display:block;margin-bottom:6px;">
                                    <input type="checkbox"
                                           name="mp3_vplayer_post_types[]"
                                           value="<?php echo esc_attr( $pt->name ); ?>"
                                        <?php checked( in_array( $pt->name, $selected_post_types, true ) ); ?>>
                                    <?php echo esc_html( $pt->label ); ?>
                                </label>
                            <?php endforeach; ?>
                        </td>
                    </tr>
                </table>
                <?php submit_button(); ?>
            </form>

            <hr>
            <h2><?php esc_html_e( 'Shortcode Usage', 'mp3-vplayer' ); ?></h2>

            <h3><?php esc_html_e( 'Single MP3 File', 'mp3-vplayer' ); ?></h3>
            <pre>[mp3_vplayer mp3file="https://vijeetdeliwala.com/song.mp3"]</pre>

            <h3><?php esc_html_e( 'Default to Current Post’s MP3 (no params)', 'mp3-vplayer' ); ?></h3>
            <pre>[mp3_vplayer]</pre>
            <p><?php esc_html_e( 'No parameters → plays mp3_url (and optional mp3_title/mp3_author) of the current post.', 'mp3-vplayer' ); ?></p>

            <h3><?php esc_html_e( 'Category Playlist', 'mp3-vplayer' ); ?></h3>
            <pre>[mp3_vplayer category="rock"]</pre>

            <h3><?php esc_html_e( 'Tag Playlist', 'mp3-vplayer' ); ?></h3>
            <pre>[mp3_vplayer tag="meditation"]</pre>

            <h3><?php esc_html_e( 'Multiple Tags', 'mp3-vplayer' ); ?></h3>
            <pre>[mp3_vplayer tag="chill,ambient"]</pre>
        </div>
        <?php
    }

    /** Meta boxes */
    public function add_mp3_meta_box() {
        foreach ( $this->post_types as $pt ) {
            add_meta_box(
                'mp3_vplayer_meta',
                __( 'MP3 Audio File', 'mp3-vplayer' ),
                array( $this, 'render_mp3_meta_box' ),
                $pt,
                'side'
            );
        }
    }

    public function render_mp3_meta_box( $post ) {
        wp_nonce_field( 'mp3_vplayer_meta_box', 'mp3_vplayer_meta_box_nonce' );

        $mp3_url    = get_post_meta( $post->ID, 'mp3_url', true );
        $mp3_title  = get_post_meta( $post->ID, 'mp3_title', true );
        $mp3_author = get_post_meta( $post->ID, 'mp3_author', true );

        $default_title  = get_the_title( $post->ID );
        $default_author = get_the_author_meta( 'display_name', $post->post_author );
        ?>
        <p>
            <label for="mp3_url">
                <strong><?php esc_html_e( 'MP3 File URL:', 'mp3-vplayer' ); ?></strong>
            </label><br>
            <input type="text"
                   id="mp3_url"
                   name="mp3_url"
                   value="<?php echo esc_attr( $mp3_url ); ?>"
                   style="width:100%; margin-bottom:6px;">
            <button type="button"
                    class="button button-small"
                    id="upload_mp3_button">
                <?php esc_html_e( 'Upload MP3', 'mp3-vplayer' ); ?>
            </button>
        </p>
        <p class="description" style="margin-top:6px;">
            <?php esc_html_e( 'Tip: Leave title/author blank to use the post title/author automatically.', 'mp3-vplayer' ); ?>
        </p>

        <p style="margin-top:12px;">
            <label for="mp3_title">
                <strong><?php esc_html_e( 'MP3 Title (optional):', 'mp3-vplayer' ); ?></strong>
            </label><br>
            <input type="text"
                   id="mp3_title"
                   name="mp3_title"
                   value="<?php echo esc_attr( $mp3_title ); ?>"
                   placeholder="<?php echo esc_attr( $default_title ); ?>"
                   style="width:100%;">
        </p>

        <p>
            <label for="mp3_author">
                <strong><?php esc_html_e( 'MP3 Author (optional):', 'mp3-vplayer' ); ?></strong>
            </label><br>
            <input type="text"
                   id="mp3_author"
                   name="mp3_author"
                   value="<?php echo esc_attr( $mp3_author ); ?>"
                   placeholder="<?php echo esc_attr( $default_author ); ?>"
                   style="width:100%;">
        </p>
        <?php
        // 🔹 NOTE: No inline <script> here anymore.
        // JS lives in js/admin.js and is enqueued via admin_enqueue_scripts.
    }

    public function save_mp3_meta( $id ) {
        if ( ! isset( $_POST['mp3_vplayer_meta_box_nonce'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
            return;
        }

        $nonce = sanitize_text_field(
            wp_unslash( $_POST['mp3_vplayer_meta_box_nonce'] ) // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        );

        if ( ! wp_verify_nonce( $nonce, 'mp3_vplayer_meta_box' ) ) {
            return;
        }

        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
            return;
        }

        if ( ! current_user_can( 'edit_post', $id ) ) {
            return;
        }

        if ( isset( $_POST['mp3_url'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
            $url = wp_unslash( $_POST['mp3_url'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
            update_post_meta( $id, 'mp3_url', esc_url_raw( $url ) );
        }

        if ( array_key_exists( 'mp3_title', $_POST ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
            $val = wp_unslash( $_POST['mp3_title'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
            $val = is_string( $val ) ? wp_kses_post( trim( $val ) ) : '';
            update_post_meta( $id, 'mp3_title', $val );
        }

        if ( array_key_exists( 'mp3_author', $_POST ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
            $val = wp_unslash( $_POST['mp3_author'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
            $val = is_string( $val ) ? sanitize_text_field( trim( $val ) ) : '';
            update_post_meta( $id, 'mp3_author', $val );
        }
    }

    /** Front-end assets */
    public function enqueue_assets() {
        wp_enqueue_style(
            'mp3-vplayer',
            plugin_dir_url( __FILE__ ) . 'css/player.css',
            array(),
            '1.0.8'
        );

        wp_enqueue_script(
            'mp3-vplayer',
            plugin_dir_url( __FILE__ ) . 'js/player.js',
            array( 'jquery' ),
            '1.0.8',
            true
        );
    }

    /**
     * Admin assets – used for meta box upload button JS.
     */
    public function enqueue_admin_assets( $hook ) {
        // Only on post edit screens.
        if ( ! in_array( $hook, array( 'post.php', 'post-new.php' ), true ) ) {
            return;
        }

        $screen = get_current_screen();
        if ( ! $screen ) {
            return;
        }

        $allowed_post_types = $this->post_types;
        if ( empty( $allowed_post_types ) ) {
            $allowed_post_types = get_option(
                'mp3_vplayer_post_types',
                array( 'post', 'page' )
            );
        }

        if ( ! in_array( $screen->post_type, $allowed_post_types, true ) ) {
            return;
        }

        // Media uploader dependency.
        wp_enqueue_media();

        // Admin JS for the meta box (no inline <script>).
        wp_enqueue_script(
            'mp3-vplayer-admin',
            plugin_dir_url( __FILE__ ) . 'js/admin.js',
            array( 'jquery' ),
            '1.0.8',
            true
        );

        // Pass translated strings to JS instead of echoing in PHP <script>.
        wp_localize_script(
            'mp3-vplayer-admin',
            'mp3vplayer_admin',
            array(
                'select_title' => esc_html__( 'Select MP3 File', 'mp3-vplayer' ),
                'button_text'  => esc_html__( 'Use this file', 'mp3-vplayer' ),
            )
        );
    }

    /** Shortcode */
    public function mp3_vplayer_shortcode( $atts ) {
        $atts = shortcode_atts(
            array(
                'mp3file'  => '',
                'file'     => '',
                'url'      => '',
                'src'      => '',
                'taxonomy' => 'category',
                'category' => '',
                'tag'      => '',
                'autoplay' => 'false',
            ),
            $atts,
            'mp3_vplayer'
        );

        $tracks = array();

        // Single URL
        $src = '';
        if ( ! empty( $atts['mp3file'] ) ) {
            $src = trim( $atts['mp3file'] );
        } else {
            foreach ( array( 'file', 'url', 'src' ) as $legacy ) {
                if ( ! empty( $atts[ $legacy ] ) ) {
                    $src = trim( $atts[ $legacy ] );
                    break;
                }
            }
        }

        if ( ! empty( $src ) ) {
            $path  = wp_parse_url( $src, PHP_URL_PATH );
            $base  = is_string( $path ) ? basename( $path ) : basename( (string) $src );
            $title = preg_replace( '/\.mp3$/i', '', $base );
            if ( ! $title ) {
                $title = 'Track';
            }
            $tracks[] = array(
                'title'  => $title,
                'url'    => esc_url_raw( $src ),
                'artist' => 'Unknown',
            );
        } elseif ( ! empty( $atts['category'] ) || ! empty( $atts['tag'] ) ) {
            // Taxonomy playlist (category/tag)
            if ( ! empty( $atts['tag'] ) ) {
                $atts['taxonomy'] = 'post_tag';
                $atts['category'] = $atts['tag'];
            }

            $taxonomy   = sanitize_text_field( $atts['taxonomy'] );
            $terms_list = array_filter(
                array_map(
                    'trim',
                    explode( ',', $atts['category'] )
                )
            );

            if ( ! taxonomy_exists( $taxonomy ) ) {

                /* translators: %s: taxonomy slug (e.g., "rock" or "chill") */
                return '<p>' . sprintf(
                    esc_html__( 'Taxonomy "%s" not found.', 'mp3-vplayer' ),
                    esc_html( $taxonomy )
                ) . '</p>';
            }

            $post_status = 'publish';
            if ( is_user_logged_in() && current_user_can( 'edit_posts' ) ) {
                $post_status = array(
                    'publish',
                    'draft',
                    'pending',
                    'future',
                    'private',
                );
            }

            $tx         = get_taxonomy( $taxonomy );
            $post_types = ( $tx && ! empty( $tx->object_type ) )
                ? (array) $tx->object_type
                : array( 'post' );

            $query = new WP_Query(
                array(
                    'post_type'              => $post_types,
                    'posts_per_page'         => -1,
                    'post_status'            => $post_status,
                    'no_found_rows'          => true,
                    'ignore_sticky_posts'    => true,
                    'update_post_term_cache' => false,
                    'update_post_meta_cache' => false,
                    'meta_query'             => array(
                        array(
                            'key'     => 'mp3_url',
                            'compare' => 'EXISTS',
                        ),
                    ),
                    'tax_query'              => array(
                        array(
                            'taxonomy' => $taxonomy,
                            'field'    => 'slug',
                            'terms'    => $terms_list,
                        ),
                    ),
                )
            );

            if ( $query->have_posts() ) {
                while ( $query->have_posts() ) {
                    $query->the_post();
                    $pid     = get_the_ID();
                    $mp3_url = get_post_meta( $pid, 'mp3_url', true );

                    if ( $mp3_url ) {
                        $meta_title  = get_post_meta( $pid, 'mp3_title', true );
                        $meta_author = get_post_meta( $pid, 'mp3_author', true );

                        $title  = ( '' !== $meta_title ) ? $meta_title : get_the_title( $pid );
                        $author = ( '' !== $meta_author ) ? $meta_author : get_the_author();

                        $tracks[] = array(
                            'title'  => $title,
                            'url'    => esc_url_raw( $mp3_url ),
                            'artist' => $author,
                        );
                    }
                }
                wp_reset_postdata();
            }
        } else {
            // Current post fallback
            $context_id = get_the_ID() ?: get_queried_object_id();
            if ( $context_id ) {
                $mp3_url = get_post_meta( $context_id, 'mp3_url', true );
                if ( $mp3_url ) {
                    $meta_title  = get_post_meta( $context_id, 'mp3_title', true );
                    $meta_author = get_post_meta( $context_id, 'mp3_author', true );

                    $title  = ( '' !== $meta_title ) ? $meta_title : get_the_title( $context_id );
                    $author = ( '' !== $meta_author )
                        ? $meta_author
                        : get_the_author_meta(
                            'display_name',
                            get_post_field( 'post_author', $context_id )
                        );

                    $tracks[] = array(
                        'title'  => $title ?: 'Track',
                        'url'    => esc_url_raw( $mp3_url ),
                        'artist' => $author ?: 'Unknown',
                    );
                }
            }
        }

        if ( empty( $tracks ) ) {
            return '<p>' . esc_html__( 'No tracks found.', 'mp3-vplayer' ) . '</p>';
        }

        $autoplay = ( strtolower( $atts['autoplay'] ) === 'true' );

        return $this->render_player( $tracks, $autoplay );
    }

    /** Renderer */
    private function render_player( $tracks, $autoplay ) {
        $tracks_json = wp_json_encode( $tracks );
        $single      = ( count( $tracks ) === 1 );

        ob_start();
        ?>
        <div class="mp3-vplayer" data-tracks="<?php echo esc_attr( $tracks_json ); ?>">
            <div class="player-main">
                <div class="player-artwork">
                    <div class="artwork-placeholder">
                        <svg width="60" height="60" viewBox="0 0 24 24" fill="none"
                             stroke="currentColor" stroke-width="1.5" aria-hidden="true">
                            <circle cx="12" cy="12" r="10" />
                            <circle cx="12" cy="12" r="3" />
                        </svg>
                    </div>
                </div>

                <div class="player-info">
                    <div class="track-title"><?php echo esc_html( $tracks[0]['title'] ); ?></div>
                    <div class="track-artist"><?php echo esc_html( $tracks[0]['artist'] ); ?></div>
                </div>

                <div class="player-controls">
                    <?php if ( ! $single ) : ?>
                        <button class="control-btn btn-previous"
                                title="<?php echo esc_attr__( 'Previous', 'mp3-vplayer' ); ?>">
                            <svg width="24" height="24" viewBox="0 0 24 24"
                                 fill="currentColor" aria-hidden="true">
                                <path d="M6 6h2v12H6zM8.5 12L19 18V6L8.5 12z" />
                            </svg>
                        </button>
                    <?php endif; ?>

                    <button class="control-btn btn-play-pause"
                            title="<?php echo esc_attr__( 'Play/Pause', 'mp3-vplayer' ); ?>">
                        <svg class="icon-play" width="28" height="28"
                             viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
                            <path d="M8 5v14l11-7z" />
                        </svg>
                        <svg class="icon-pause" width="28" height="28"
                             viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"
                             style="display:none">
                            <path d="M6 4h4v16H6zm8 0h4v16h-4z" />
                        </svg>
                    </button>

                    <?php if ( ! $single ) : ?>
                        <button class="control-btn btn-next"
                                title="<?php echo esc_attr__( 'Next', 'mp3-vplayer' ); ?>">
                            <svg width="24" height="24" viewBox="0 0 24 24"
                                 fill="currentColor" aria-hidden="true">
                                <path d="M16 6h2v12h-2zM6 18l10.5-6L6 6v12z" />
                            </svg>
                        </button>
                    <?php endif; ?>
                </div>

                <div class="player-progress">
                    <span class="time-current">0:00</span>
                    <div class="progress-bar">
                        <div class="progress-track">
                            <div class="progress-fill"></div>
                        </div>
                    </div>
                    <span class="time-duration">0:00</span>
                </div>
            </div>

            <?php if ( ! $single ) : ?>
                <div class="player-playlist">
                    <div class="playlist-header">
                        <?php echo esc_html__( 'Now Playing', 'mp3-vplayer' ); ?>
                    </div>
                    <div class="playlist-tracks">
                        <?php foreach ( $tracks as $index => $track ) : ?>
                            <div class="playlist-item"
                                 data-index="<?php echo esc_attr( $index ); ?>">
                                <div class="playlist-item-number">
                                    <?php echo esc_html( $index + 1 ); ?>
                                </div>
                                <div class="playlist-item-info">
                                    <div class="playlist-item-title">
                                        <?php echo esc_html( $track['title'] ); ?>
                                    </div>
                                    <div class="playlist-item-artist">
                                        <?php echo esc_html( $track['artist'] ); ?>
                                    </div>
                                </div>
                                <div class="playlist-item-duration">--:--</div>
                            </div>
                        <?php endforeach; ?>
                    </div>
                </div>
            <?php endif; ?>

            <audio preload="metadata" <?php echo $autoplay ? 'autoplay="autoplay"' : ''; ?>>
                <source src="<?php echo esc_url( $tracks[0]['url'] ); ?>" type="audio/mpeg" />
            </audio>
        </div>
        <?php
        return ob_get_clean();
    }
}

new MP3_VPlayer();
