<?php

/**
 * Plugin Name: Gene Scroll Hero
 * Plugin URI: https://gene-wp.com/
 * Description: Turn your homepage into a scene from a film. Add a full-screen background video that plays as visitors scroll — with your headline over it. Pick a video, type a heading, done. No code, and it never breaks your layout. Free, with an optional Pro upgrade unlocked by a license.
 * Version: 3.6.1
 * Requires at least: 6.4
 * Requires PHP: 7.4
 * Author: One Craft
 * Author URI: https://onecraft-ne.jp
 * License: GPL-2.0-or-later
 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain: gene-section-builder
 * Domain Path: /languages
 *
 * @package GENE_Blocks
 *
 * Single freemium plugin. This is the WordPress.org (free) build; the Pro tier
 * — multiple headings that swap on scroll, free-placement timeline, and scroll
 * controls — lives in this same code and is gated in the editor by the license
 * (window.geneMotionConfig.isPro). No separate Pro plugin, no mirror to keep in
 * sync. Buying a license and activating it flips isPro true; nothing changes for
 * a visitor (saved markup renders for everyone). Freemius (product 30655) handles
 * licensing / checkout / updates.
 */
if ( !defined( 'ABSPATH' ) ) {
    exit;
}
define( 'GENE_BLOCKS_VERSION', '3.6.1' );
define( 'GENE_BLOCKS_DIR', plugin_dir_path( __FILE__ ) );
define( 'GENE_BLOCKS_URI', plugin_dir_url( __FILE__ ) );
/* =========================================================================
   0. Freemius SDK — licensing / checkout / updates (freemium)
   -------------------------------------------------------------------------
   Freemius product id 30655 (reused from the former Pro plugin, keeping its
   Pro / Agency plans and public key). This is the WordPress.org *free* build:
   'is_premium' => false and the Pro features ship inside it, JS-gated — so we
   gate on the license *state* (is_paying_or_trial), not premium-code context,
   and a single build serves everyone.

   ⚠ The Freemius product slug below must match product 30655's slug in the
   Freemius dashboard EXACTLY (currently 'GeneScrollHero'), or license activation
   breaks with a "you do not have permission" error. This is the Freemius product
   identifier only — the WordPress.org slug / plugin folder / text domain stay
   'gene-section-builder' (unchanged). The public key (pk_) is publishable; the
   secret key (sk_) is never in code (wp-config only, and its constant name
   follows the slug: WP_FS__GeneScrollHero_SECRET_KEY).
   ========================================================================= */
if ( !defined( 'GENE_BLOCKS_FS_ID' ) ) {
    define( 'GENE_BLOCKS_FS_ID', '30655' );
    define( 'GENE_BLOCKS_FS_SLUG', 'GeneScrollHero' );
    define( 'GENE_BLOCKS_FS_PUBLIC_KEY', 'pk_329ff6198f39cb07fb706e9026a82' );
}
if ( !function_exists( 'gene_blocks_fs' ) ) {
    function gene_blocks_fs() {
        global $gene_blocks_fs;
        if ( !isset( $gene_blocks_fs ) ) {
            $sdk_path = GENE_BLOCKS_DIR . 'freemius/start.php';
            // No-op until the SDK and product keys are present.
            if ( !file_exists( $sdk_path ) || '' === GENE_BLOCKS_FS_ID || '' === GENE_BLOCKS_FS_PUBLIC_KEY ) {
                $gene_blocks_fs = null;
                return null;
            }
            require_once $sdk_path;
            $gene_blocks_fs = fs_dynamic_init( array(
                'id'               => GENE_BLOCKS_FS_ID,
                'slug'             => GENE_BLOCKS_FS_SLUG,
                'premium_slug'     => GENE_BLOCKS_FS_SLUG,
                'type'             => 'plugin',
                'public_key'       => GENE_BLOCKS_FS_PUBLIC_KEY,
                'is_premium'       => false,
                'is_premium_only'  => false,
                'has_addons'       => false,
                'has_paid_plans'   => true,
                // Restored after Freemius processing (it strips this from the
                // free build): tells the SDK this single build is itself the
                // premium code, JS-gated by license, so the 'Activate License' UI
                // shows on the free build. Required for licensing to work.
                'has_premium_version' => false,
                'is_org_compliant' => true,
                'menu'             => array(
                    'slug'    => 'gene-blocks',
                    'account' => true,
                    'contact' => false,
                    'support' => false,
                ),
                'is_live'          => true,
            ) );
        }
        return $gene_blocks_fs;
    }

    gene_blocks_fs();
    do_action( 'gene_blocks_fs_loaded' );
}
/**
 * Whether the Pro tier is unlocked (an active paid license or trial).
 *
 * Freemium single build: the Pro features live in this free build and are
 * JS-gated, so we check the license *state* — which is true even on the org
 * (free) build once a license is activated — rather than can_use_premium_code(),
 * which is only true on a separate premium build. No Freemius / no license →
 * false → the free tier (the previous default). Saved markup renders for every
 * visitor regardless of this.
 *
 * @return bool
 */
function gene_blocks_has_license() {
    // Local testing escape hatch. Off by default; add
    //   define( 'GENE_BLOCKS_FORCE_PRO', true );
    // to wp-config.php to unlock the Pro tier without Freemius license activation
    // (useful while the Freemius product finishes its freemium setup). This only
    // affects the editor gate — the front end renders the same for everyone.
    if ( defined( 'GENE_BLOCKS_FORCE_PRO' ) && GENE_BLOCKS_FORCE_PRO ) {
        return true;
    }
    $fs = ( function_exists( 'gene_blocks_fs' ) ? gene_blocks_fs() : null );
    if ( !is_object( $fs ) ) {
        return false;
        // no Freemius configured → free tier
    }
    if ( method_exists( $fs, 'is_paying_or_trial' ) && $fs->is_paying_or_trial() ) {
        return true;
    }
    // Fallback for a real premium build, should one ever be deployed.
    if ( method_exists( $fs, 'can_use_premium_code' ) && $fs->can_use_premium_code() ) {
        return true;
    }
    return false;
}

/* =========================================================================
   1. Text Domain
   -------------------------------------------------------------------------
   No manual load_plugin_textdomain(): hosted on WordPress.org, so the
   `gene-section-builder` text domain is loaded automatically (just-in-time)
   from WordPress.org language packs. The block-editor UI is translated in JS.
   ========================================================================= */
/* =========================================================================
   2. "GENE Motion" block category
   ========================================================================= */
function gene_blocks_register_motion_category(  $categories  ) {
    foreach ( $categories as $cat ) {
        if ( isset( $cat['slug'] ) && 'gene-motion' === $cat['slug'] ) {
            return $categories;
        }
    }
    return array_merge( array(array(
        'slug'  => 'gene-motion',
        'title' => __( 'GENE Motion', 'gene-section-builder' ),
        'icon'  => 'images-alt2',
    )), $categories );
}

add_filter(
    'block_categories_all',
    'gene_blocks_register_motion_category',
    10,
    1
);
/* =========================================================================
   3. Register the bundled GENE Motion blocks
   -------------------------------------------------------------------------
   The block lives in build/<name> with a block.json declaring its
   editorScript / style / viewScript. viewScript keeps the front-end behaviour
   loaded only on pages that actually use the block.

   The free plugin bundles just the Scroll Hero. Its Pro extras (multiple
   headings that swap on scroll, and fine scroll controls) are gated in the
   editor via geneMotionConfig.isPro, not by a separate block.

   Coexistence guard: the block lives in the gene-motion/* namespace, shared
   with GENE Motion Blocks Pro and the standalone GENE Motion Blocks. If either
   of those is also active it registers the same block name first (default
   priority on `init`); we run at priority 20 and skip any block that is already
   registered, so there is no "block already registered" collision.
   ========================================================================= */
function gene_blocks_register_motion_blocks() {
    $blocks = array('hero');
    $registry = WP_Block_Type_Registry::get_instance();
    foreach ( $blocks as $block ) {
        if ( $registry->is_registered( 'gene-motion/' . $block ) ) {
            continue;
        }
        $dir = GENE_BLOCKS_DIR . 'build/' . $block;
        if ( file_exists( $dir . '/block.json' ) ) {
            register_block_type( $dir );
        }
    }
}

add_action( 'init', 'gene_blocks_register_motion_blocks', 20 );
/* =========================================================================
   4. Editor config — window.geneMotionConfig
   -------------------------------------------------------------------------
   Each block's edit.js reads this (shared pro-gate reads geneBlocksConfig ||
   geneMotionConfig). isPro governs the editor only; the saved front-end markup
   renders for every visitor, so nothing an editor does here can break a page.
   ========================================================================= */
function gene_blocks_editor_config() {
    $upgrade_url = 'https://gene-wp.com/';
    $account_url = '';
    $fs = ( function_exists( 'gene_blocks_fs' ) ? gene_blocks_fs() : null );
    if ( is_object( $fs ) ) {
        if ( method_exists( $fs, 'get_upgrade_url' ) ) {
            $u = $fs->get_upgrade_url();
            if ( $u ) {
                $upgrade_url = $u;
            }
        }
        if ( method_exists( $fs, 'get_account_url' ) ) {
            $account_url = $fs->get_account_url();
        }
    }
    $config = array(
        'isPro'      => gene_blocks_has_license(),
        'pluginUrl'  => untrailingslashit( GENE_BLOCKS_URI ),
        'upgradeUrl' => $upgrade_url,
        'accountUrl' => $account_url,
        'locale'     => determine_locale(),
    );
    wp_add_inline_script( 'wp-blocks', 'window.geneMotionConfig = ' . wp_json_encode( $config ) . ';', 'before' );
}

add_action( 'enqueue_block_editor_assets', 'gene_blocks_editor_config' );
/* =========================================================================
   5. Admin info page (a small landing under "GENE Motion")
   ========================================================================= */
function gene_blocks_admin_menu() {
    add_menu_page(
        __( 'Gene Scroll Hero', 'gene-section-builder' ),
        'Scroll Hero',
        'edit_posts',
        'gene-blocks',
        'gene_blocks_admin_page',
        'dashicons-cover-image',
        58
    );
}

add_action( 'admin_menu', 'gene_blocks_admin_menu' );
function gene_blocks_admin_page() {
    echo '<div class="wrap">';
    echo '<h1>' . esc_html__( 'Gene Scroll Hero', 'gene-section-builder' ) . '</h1>';
    echo '<p style="max-width:760px;font-size:14px">' . esc_html__( 'Scroll Hero puts a full-screen background video (or image) at the top of your page, with your headline over it — and the video plays as visitors scroll. It is a native block, loads no external libraries, and never breaks your pages. Everything you need is right here, so there is nothing extra to read.', 'gene-section-builder' ) . '</p>';
    // ---- License entry, front and center (so it never feels buried) ----
    // A serviceware / org-compliant free build activates a license through
    // Freemius's license-activation modal — the same dialog the Plugins-page
    // "Activate License" link opens. We do NOT link to the Account page:
    // Freemius only registers admin.php?page={slug}-account once the site is
    // connected (is_registered()), so before that a deep link there returns
    // "Sorry, you are not allowed to access this page." Instead we render that
    // modal on this page and open it with the generic
    // ".activate-license-trigger.{affix}" hook Freemius delegates from <body>.
    // Works whether or not the site is connected. Shown only when unlicensed.
    $gb_fs = ( function_exists( 'gene_blocks_fs' ) ? gene_blocks_fs() : null );
    $gb_affix = '';
    $gb_can_activate = is_object( $gb_fs ) && !gene_blocks_has_license() && method_exists( $gb_fs, 'get_unique_affix' ) && method_exists( $gb_fs, '_add_license_activation_dialog_box' );
    if ( $gb_can_activate ) {
        $gb_affix = $gb_fs->get_unique_affix();
        // Put the license-activation modal (HTML + JS) on this page so the
        // trigger button below has something to open.
        add_action( 'admin_footer', array($gb_fs, '_add_license_activation_dialog_box') );
        echo '<div style="margin:14px 0 6px;padding:14px 18px;border:1px solid #dcdcde;border-radius:8px;background:#f6f7f7;display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;max-width:760px">';
        echo '<span style="font-size:13px;color:#1d2327">' . esc_html__( 'Already bought Scroll Hero Pro?', 'gene-section-builder' ) . '</span>';
        echo '<a class="button button-primary activate-license-trigger ' . esc_attr( $gb_affix ) . '" href="#">' . esc_html__( 'Enter your license key', 'gene-section-builder' ) . '</a>';
        echo '</div>';
    }
    // ---- Getting started (built-in guide, so no external docs are needed) ----
    echo '<hr>';
    echo '<h2>' . esc_html__( 'Getting started', 'gene-section-builder' ) . '</h2>';
    $steps = array(array(__( 'Add the Scroll Hero block', 'gene-section-builder' ), __( 'In any post or page, open the block inserter (+) and search for "Scroll Hero", or find it under the "GENE Motion" category. Click to insert it.', 'gene-section-builder' )), array(__( 'Choose a background', 'gene-section-builder' ), __( 'In the block settings on the right, set a background — a video or an image. A video plays as visitors scroll; an image gives a clean full-screen hero.', 'gene-section-builder' )), array(__( 'Type your heading', 'gene-section-builder' ), __( 'Add your headline in the sidebar. That is the whole block — a background and a heading.', 'gene-section-builder' )));
    echo '<div style="max-width:760px;margin:16px 0 8px">';
    $n = 0;
    foreach ( $steps as $s ) {
        $n++;
        echo '<div style="position:relative;padding:0 0 22px 62px;min-height:42px">';
        echo '<span style="position:absolute;left:0;top:0;width:42px;height:42px;border-radius:50%;background:#2271b1;color:#fff;font-weight:700;font-size:19px;line-height:42px;text-align:center">' . (int) $n . '</span>';
        echo '<h3 style="margin:2px 0 4px;font-size:15px">' . esc_html( $s[0] ) . '</h3>';
        echo '<p style="margin:0;color:#50575e;font-size:13px;line-height:1.5">' . esc_html( $s[1] ) . '</p>';
        echo '</div>';
    }
    echo '</div>';
    echo '<h3 style="margin:18px 0 8px">' . esc_html__( 'The controls', 'gene-section-builder' ) . '</h3>';
    $controls = array(array(__( 'Background', 'gene-section-builder' ), __( 'Pick a video or an image. A video plays as visitors scroll down and rewinds as they scroll up.', 'gene-section-builder' )), array(__( 'Dim overlay', 'gene-section-builder' ), __( 'Darkens the background a little so your heading stays easy to read on top of it.', 'gene-section-builder' )), array(__( 'Heading', 'gene-section-builder' ), __( 'A small label, your headline, and a sub-line — the words that sit over the background.', 'gene-section-builder' )));
    echo '<ul style="max-width:760px;margin:0;padding:0;list-style:none">';
    foreach ( $controls as $c ) {
        echo '<li style="padding:8px 0;border-bottom:1px solid #f0f0f1;font-size:13px;color:#50575e">';
        echo '<strong style="color:#1d2327">' . esc_html( $c[0] ) . '</strong>: ' . esc_html( $c[1] );
        echo '</li>';
    }
    echo '</ul>';
    echo '<h3 style="margin:18px 0 8px">' . esc_html__( 'What visitors see', 'gene-section-builder' ) . '</h3>';
    echo '<p style="max-width:760px;color:#50575e;font-size:13px;line-height:1.6;margin:0">' . esc_html__( 'Scroll down and the video plays; scroll back up and it rewinds — with your heading right on top. A short clip (a few seconds) plays the smoothest.', 'gene-section-builder' ) . '</p>';
    echo '<h3 style="margin:18px 0 8px">' . esc_html__( 'It never breaks', 'gene-section-builder' ) . '</h3>';
    echo '<p style="max-width:760px;color:#50575e;font-size:13px;line-height:1.6;margin:0">' . esc_html__( 'On an old browser, with motion turned off, or with JavaScript disabled, the video simply loops gently and your heading still shows. Nothing loads from a third-party server, the page never gains a sideways scrollbar, and if you deactivate the plugin your content stays put.', 'gene-section-builder' ) . '</p>';
    // ---- Help & reviews (static links on this plugin's own page — WP.org compliant, no nag) ----
    echo '<hr>';
    echo '<h2>' . esc_html__( 'Questions, or want to say thanks?', 'gene-section-builder' ) . '</h2>';
    echo '<p style="max-width:760px;font-size:13px;color:#50575e">' . esc_html__( 'Ask questions and share what you build in our Discord community. And if Scroll Hero is useful to you, a quick review really helps other people find it.', 'gene-section-builder' ) . '</p>';
    echo '<p>';
    echo '<a class="button button-secondary" href="' . esc_url( 'https://discord.gg/kgmKgxdRf' ) . '" target="_blank" rel="noopener noreferrer">' . esc_html__( 'Join our Discord', 'gene-section-builder' ) . '</a> ';
    echo '<a class="button button-secondary" href="' . esc_url( 'https://wordpress.org/support/plugin/gene-section-builder/reviews/' ) . '" target="_blank" rel="noopener noreferrer">' . esc_html__( '★ Leave a review', 'gene-section-builder' ) . '</a>';
    echo '</p>';
    // Pro tier — unlocked in place by a license (no separate plugin). When a
    // license is active we say so; otherwise we show the Pro features as locked
    // cards with an Upgrade button. Informational only: no fake block UI, no nag,
    // and it disables nothing — the free Scroll Hero keeps working.
    $licensed = gene_blocks_has_license();
    $fs = ( function_exists( 'gene_blocks_fs' ) ? gene_blocks_fs() : null );
    $upgrade_url = 'https://gene-wp.com/';
    $account_url = '';
    if ( is_object( $fs ) ) {
        if ( method_exists( $fs, 'get_upgrade_url' ) ) {
            $u = $fs->get_upgrade_url();
            if ( $u ) {
                $upgrade_url = $u;
            }
        }
        if ( method_exists( $fs, 'get_account_url' ) ) {
            $account_url = $fs->get_account_url();
        }
    }
    echo '<hr>';
    if ( $licensed ) {
        echo '<h2>' . esc_html__( 'Scroll Hero Pro is active', 'gene-section-builder' ) . '</h2>';
        echo '<p style="max-width:760px;font-size:13px;color:#50575e">' . esc_html__( 'Thank you! In the block you can now add several headings that appear one after another, place them anywhere on a timeline, and fine-tune the scroll length.', 'gene-section-builder' ) . '</p>';
        if ( $account_url ) {
            echo '<p><a class="button button-secondary" href="' . esc_url( $account_url ) . '">' . esc_html__( 'Manage license', 'gene-section-builder' ) . '</a></p>';
        }
        echo '</div>';
        return;
    }
    echo '<h2>' . esc_html__( 'Do more with Scroll Hero Pro', 'gene-section-builder' ) . '</h2>';
    echo '<p>' . esc_html__( 'Your free Scroll Hero keeps working with a video background and one heading. A license unlocks the Pro tier right here in the same block:', 'gene-section-builder' ) . '</p>';
    $pro_features = array(
        array(
            'icon'  => 'dashicons-list-view',
            'title' => __( 'Headings that appear one by one', 'gene-section-builder' ),
            'desc'  => __( 'Add several headings and they show up one after another as visitors scroll — first one line, then the next, like a story.', 'gene-section-builder' ),
        ),
        array(
            'icon'  => 'dashicons-move',
            'title' => __( 'Place headings anywhere on a timeline', 'gene-section-builder' ),
            'desc'  => __( 'Drag each heading onto the hero and set when it appears and leaves as visitors scroll — like slides on a timeline.', 'gene-section-builder' ),
        ),
        array(
            'icon'  => 'dashicons-admin-settings',
            'title' => __( 'Fine scroll controls', 'gene-section-builder' ),
            'desc'  => __( 'Choose how long the scroll lasts, so you can dial in exactly how the hero feels.', 'gene-section-builder' ),
        ),
        array(
            'icon'  => 'dashicons-admin-appearance',
            'title' => __( 'Fonts & button shapes', 'gene-section-builder' ),
            'desc'  => __( 'Pick a font preset and a button shape for the hero. (Coloring the heading and buttons is free for everyone.)', 'gene-section-builder' ),
        ),
        array(
            'icon'  => 'dashicons-email-alt',
            'title' => __( 'Priority email support', 'gene-section-builder' ),
            'desc'  => __( 'Get help straight from the makers.', 'gene-section-builder' ),
        )
    );
    echo '<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:16px;max-width:920px;margin:16px 0 24px">';
    foreach ( $pro_features as $f ) {
        echo '<div style="position:relative;border:1px solid #dcdcde;border-radius:8px;padding:18px;background:#fff">';
        echo '<span style="position:absolute;top:12px;right:12px;font-size:11px;font-weight:600;color:#fff;background:#2271b1;border-radius:10px;padding:2px 9px 2px 7px">' . '<span class="dashicons dashicons-lock" style="font-size:12px;width:12px;height:12px;vertical-align:-2px"></span> ' . esc_html__( 'Pro', 'gene-section-builder' ) . '</span>';
        echo '<span class="dashicons ' . esc_attr( $f['icon'] ) . '" style="font-size:28px;width:28px;height:28px;color:#2271b1"></span>';
        echo '<h3 style="margin:10px 0 6px;font-size:15px">' . esc_html( $f['title'] ) . '</h3>';
        echo '<p style="margin:0;color:#50575e;font-size:13px;line-height:1.5">' . esc_html( $f['desc'] ) . '</p>';
        echo '</div>';
    }
    echo '</div>';
    echo '<p><a class="button button-primary" href="' . esc_url( $upgrade_url ) . '">' . esc_html__( 'Upgrade to Pro', 'gene-section-builder' ) . '</a>';
    // Same Freemius license-activation modal as the button up top (opened via the
    // ".activate-license-trigger.{affix}" hook). Reuses $gb_can_activate/$gb_affix
    // computed near the top of this function; we only reach here when unlicensed.
    if ( $gb_can_activate ) {
        echo ' <a class="button button-secondary activate-license-trigger ' . esc_attr( $gb_affix ) . '" href="#">' . esc_html__( 'Already have a license? Enter it', 'gene-section-builder' ) . '</a>';
    }
    echo '</p>';
    echo '</div>';
}

/* =========================================================================
   5b. Plugins-list row link — upgrade to the Pro tier
   -------------------------------------------------------------------------
   A single static link in this plugin's row on the Plugins screen (not a notice
   or nag). Hidden once a license is active. Points at the Freemius upgrade URL.
   ========================================================================= */
function gene_blocks_plugin_row_meta(  $links, $file  ) {
    if ( plugin_basename( __FILE__ ) === $file && !gene_blocks_has_license() ) {
        $fs = ( function_exists( 'gene_blocks_fs' ) ? gene_blocks_fs() : null );
        $url = 'https://gene-wp.com/';
        if ( is_object( $fs ) && method_exists( $fs, 'get_upgrade_url' ) && $fs->get_upgrade_url() ) {
            $url = $fs->get_upgrade_url();
        }
        $links[] = '<a href="' . esc_url( $url ) . '">' . esc_html__( 'Upgrade to Pro', 'gene-section-builder' ) . '</a>';
    }
    return $links;
}

add_filter(
    'plugin_row_meta',
    'gene_blocks_plugin_row_meta',
    10,
    2
);
/* =========================================================================
   5c. Hide the install Public/Secret Key rows on the Freemius account screen so
   customers never see them (CSS-only; the bundled SDK stays untouched).
   ========================================================================= */
function gene_blocks_hide_account_keys() {
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only page-slug check to scope admin CSS; no form data is processed and no state changes.
    $page = ( isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : '' );
    if ( 0 !== strpos( $page, 'gene-blocks' ) ) {
        return;
    }
    echo '<style>#fs_account_details tr.fs-field-site_public_key,#fs_account_details tr.fs-field-site_secret_key{display:none !important;}</style>';
}

add_action( 'admin_head', 'gene_blocks_hide_account_keys' );