<?php
/**
 * Plugin Name:       Lcp Gallery
 * Description:       Example block scaffolded with Create Block tool.
 * Requires at least: 6.1
 * Requires PHP:      7.0
 * Version:           0.1.0
 * Author:            The WordPress Contributors
 * License:           GPL-2.0-or-later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       lcp
 *
 * @package CreateBlock
 */

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

/**
 * Registers the block using the metadata loaded from the `block.json` file.
 * Behind the scenes, it registers also all assets so they can be enqueued
 * through the block editor in the corresponding context.
 *
 * @see https://developer.wordpress.org/reference/functions/register_block_type/
 */
if (!function_exists('lcp_random_string')) {

    function lcp_random_string($length = 8, $css_compliant = false, $include_character_types = '') {
        // Define character sets
        $lowercase = 'abcdefghijklmnopqrstuvwxyz';
        $uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $numbers = '0123456789';
        $special_chars = '!@#$%^&*()_+-=[]{}|;:,.<>?';
        $all_chars = $lowercase . $uppercase . $numbers . $special_chars;

        // Default to using all characters if no specific types are provided
        if (empty($include_character_types)) {
            $include_character_types = 'all';
        }

        // Build the allowed character set
        $char_set = '';

        if ($include_character_types === 'all') {
            // Include everything
            $char_set = $all_chars;
        } else {
            // Add specific types requested
            if (strpos($include_character_types, 'lowercase') !== false) {
                $char_set .= $lowercase;
            }
            if (strpos($include_character_types, 'uppercase') !== false) {
                $char_set .= $uppercase;
            }
            if (strpos($include_character_types, 'numbers') !== false) {
                $char_set .= $numbers;
            }
            if (strpos($include_character_types, 'special') !== false) {
                $char_set .= $special_chars;
            }
        }

        // Ensure that the string is valid for CSS (starts with a letter and can only include letters, digits, hyphens, or underscores)
        $css_char_set = $lowercase . $uppercase . $numbers . '-_';

        // Random string generation logic
        $random_string = '';
        $first_char = '';

        // If CSS compliant, start with a letter (either lowercase or uppercase)
        if ($css_compliant) {
            // Ensure the first character is a letter (CSS compliant start)
            $first_char = $lowercase[rand(0, strlen($lowercase) - 1)];
            $random_string .= $first_char;
            $length--; // Decrease length by 1 as we already added the first char
        }

        // Fill the rest of the string with random characters from the valid set (CSS compliant)
        for ($i = 0; $i < $length; $i++) {
            // Use only characters that are CSS compliant (letters, digits, hyphens, or underscores)
            $random_string .= $css_char_set[rand(0, strlen($css_char_set) - 1)];
        }

        // Return the string
        return $random_string;
    }
}


// Return a valid array of Media IDs
    // Used to return custom meta fields/table fields data as an array
function validate_media_ids($input) {
    // Check if the input is a serialized array (e.g., 'a:2:{i:0;s:2:"63";i:1;s:2:"64";}')
    if (is_string($input) && (@unserialize($input) !== false || $input === 'b:0;')) {
        // If serialized, unserialize it
        $media_ids = unserialize($input);

        // Ensure the unserialized data is an array
        if (is_array($media_ids)) {
            // Return the array of IDs (ensure they're integers)
            return array_map('intval', array_filter($media_ids));
        }
    }

    // Check if the input is a comma-separated string of IDs (e.g., "112,512,581")
    if (is_string($input)) {
        // Split the string into an array using commas as separators
        $media_ids = array_map('intval', explode(',', $input));

        // Filter out any invalid IDs (non-numeric or empty)
        return array_filter(array_unique($media_ids));
    }

    // Check if the input is already an array (e.g., [63, 64, 112])
    if (is_array($input)) {
        // Ensure the array only contains integers
        return array_filter(array_map('intval', $input));
    }

    // Return an empty array if the input format is not recognized
    return [];
}


// Return an array of Media IDs
function get_media_ids($attributes) {
    // Manual Source
    if ($attributes['source'] == "manual" && isset($attributes['galleryItems'])) {
        // Extract 'id' from each item in the 'galleryItems' array
        $media_ids = array_map(function($item) {
            return $item['id']; // Return the 'id' value from each array item
        }, $attributes['galleryItems']); // Use $attributes['galleryItems'] here

        // Check if we need to include the post thumbnail
        if ($attributes['includePostThumbnail']) {
            // Get the featured image (post thumbnail) ID
            $featured_media_id = get_post_thumbnail_id(get_the_ID());
            if ($featured_media_id) {
                // Add the featured media ID to the beginning of the array
                array_unshift($media_ids, $featured_media_id);
            }
        }

        // Post Meta Source
        return $media_ids;
    } 
    
    // Meta Field Source
    elseif (isset($attributes['source']) && $attributes['source'] == "metaField") {
        // Ensure 'sourceMetaField' exists in the attributes array
        if (isset($attributes['sourceMetaField'])) {
            // Retrieve the raw data directly from the custom field (it will be automatically unserialized by WordPress if it's a serialized string)
            $raw_media_ids = get_post_meta(get_the_ID(), $attributes['sourceMetaField'], true);
            // Pass the raw data to the helper function to decide how to process it
            $media_ids = validate_media_ids($raw_media_ids);
            // Return the processed media IDs
            return $media_ids;
        }
    }

    // Return an empty array if no gallery items or source is not handled
    return [];
}



//Get the gallery items from the media IDs
function get_gallery_items_data($media_ids) {
    $gallery_items = array();

    // Loop through each media ID
    foreach ($media_ids as $media_id) {
        // Get the full-size image URL
        $image_url = wp_get_attachment_url($media_id);
        
        // Get the attachment metadata, including available image sizes
        $metadata = wp_get_attachment_metadata($media_id);
        
        // Initialize the `data-lg-size` and `data-responsive` attributes
        $lg_size = '';
        $responsive_data = '';
        
        // Check if metadata exists and extract image sizes
        if (isset($metadata['sizes'])) {
            // Loop through the sizes and build the data-lg-size and data-responsive attributes
            foreach ($metadata['sizes'] as $size_name => $size_info) {
                // data-lg-size format: width-height-width (for each image size)
                $lg_size .= $size_info['width'] . '-' . $size_info['height'] . '-'. $size_info['width'] . ', ';
                
                // Get the URL of the size's image for data-responsive
                $file_url = wp_get_attachment_image_url($media_id, $size_name);  // Get the URL of the size's image
                
                // Add the image URL and width to the data-responsive string
                if ($file_url) {
                    $responsive_data .= $file_url . ' ' . $size_info['width'] . ', ';
                }
            }

            // Clean up trailing commas and spaces
            $lg_size = rtrim($lg_size, ', ');
            $responsive_data = rtrim($responsive_data, ', ');
        }

        // Get the caption from the media's post (if available)
        $caption = get_post_field('post_excerpt', $media_id); // Retrieves the caption (if set)
        
        // Get the alt text from the media's metadata (if available)
        $alt_text = get_post_meta($media_id, '_wp_attachment_image_alt', true);
        
        // Use a fallback for alt text if it's empty


        // Add the gallery item to the array
        $gallery_items[] = array(
            'src' => esc_url($image_url), // Full-size image URL
            'responsive' => esc_attr($responsive_data), // Responsive srcset
            'thumb' => wp_get_attachment_image_url($media_id, 'thumbnail'), // Thumbnail URL
            'medium' => wp_get_attachment_image_url($media_id, 'medium'), // Medium URL
            'subHtml' => !empty($caption) ? 
                '<div class="lightGallery-captions"><p>' . esc_html($caption) . '</p></div>' :
                '<div><h4>' . esc_html($alt_text) . '</h4></div>',
            'lg_size' => $lg_size, // The data-lg-size string
            'responsive_data' => $responsive_data, // The data-responsive string
            'size' => 'full' // Added size attribute for better responsive handling
        );
    }

    // Return the array of gallery items
    return $gallery_items;
}

// Build the HTML for the gallery items
function build_gallery_items_html($gallery_items_data, $attributes) {
    // Initialize an empty string for the HTML output
    $html = '';
    
    // If the gallery is set to render dynamically, limit the number of items if applicable
    // otherwise, return all items
    if ($attributes['dynamic']) {
        // Get the value of 'maxInitialItems' from attributes, default to 0 if not set
        $max_initial_items = isset($attributes['maxInitialItems']) ? (int) $attributes['maxInitialItems'] : 0;
        // Limit the number of gallery items based on maxInitialItems
        if ($max_initial_items > 0) {
            // Slice the array to only include the first $max_initial_items items
            $gallery_items_data = array_slice($gallery_items_data, 0, $max_initial_items);
        }
    }

    // Loop through each gallery item and create the HTML
    foreach ($gallery_items_data as $item) {
        $src = $item['src'];
        $thumb = $item['thumb'];
        $medium = $item['medium'];
        $sub_html = $item['subHtml'];
        $lg_size = $item['lg_size']; // Fetch the lg_size data for the current item
        $responsive = $item['responsive_data']; // Fetch the responsive data (URLs + widths)

        // Create the HTML structure for each item, including data-responsive
        $html .= '
        <a class="lcp-gallery-item" data-lg-size="' . esc_attr($lg_size) . '" 
           data-responsive="' . esc_attr($responsive) . '" 
           class="lcp-gallery-item" 
           data-src="' . esc_url($src) . '" 
           data-sub-html="' . esc_attr($sub_html) . '">
            <img class="img-fluid" src="' . esc_url($medium) . '" />
        </a>';
    }

    // Return the constructed HTML
    return $html;
}



// Array of required plugins
function build_plugins_json($attributes) {
        // Initialize the plugins array
        $plugins = array();

        // Check if lgSettings['zoom'] is true and add 'lgShare' to the plugins array
        if (isset($attributes['lgSettings']['zoom']) && $attributes['lgSettings']['zoom'] === true) {
            $plugins[] = 'lgZoom';
        }
        // Check if lgSettings['share'] is true and add 'lgShare' to the plugins array
        if (isset($attributes['lgSettings']['share']) && $attributes['lgSettings']['share'] === true) {
            $plugins[] = 'lgShare';
        }
        // Check if lgSettings['share'] is true and add 'lgShare' to the plugins array
        if (isset($attributes['lgSettings']['autoplay']) && $attributes['lgSettings']['autoplay'] === true) {
                $plugins[] = 'lgAutoplay';
        }
        if (isset($attributes['lgSettings']['fullScreen']) && $attributes['lgSettings']['fullScreen'] === true) {
            $plugins[] = 'lgFullScreen';
        }
        if (isset($attributes['lgSettings']['thumbnail']) && $attributes['lgSettings']['thumbnail'] === true) {
            $plugins[] = 'lgThumbnail';
        }
        if (isset($attributes['lgSettings']['rotate']) && $attributes['lgSettings']['rotate'] === true) {
            $plugins[] = 'lgRotate';
        }
        // JSON encode the plugins array and return the result
        return ($plugins);

}


// Build array of dynamic elements - returns an array
function build_dynamic_elements_array($gallery_items_data) {
    $dynamic_elements = [];

    foreach ($gallery_items_data as $item) {
        $src = $item['src'];
        $responsive = $item['responsive'] ?: ''; // Fallback if responsive is empty
        $thumb = $item['thumb'];
        $subHtml = $item['subHtml'];
        $alt_text = isset($item['alt_text']) ? $item['alt_text'] : 'No title available';

        $subHtmlContent = '<div class="lightGallery-captions"><h4>' . esc_html($alt_text) . '</h4><p>' . esc_html($subHtml) . '</p></div>';

        $dynamic_elements[] = [
            'src' => esc_url($src),
            'responsive' => esc_attr($responsive),
            'thumb' => esc_url($thumb),
            'subHtml' => $subHtmlContent,
        ];
    }

    return $dynamic_elements;
}

// Build the gallery settings JSON
function build_gallery_settings_json($attributes, $unique_class) {
    $container_class = "." . $unique_class;
    
    // Step 1: Get the media IDs based on the attributes
    $media_ids = get_media_ids($attributes);
    if (empty($media_ids)) {
        return json_encode(['error' => 'No media IDs found']);
    }

    // Step 2: Get the gallery items data
    $gallery_items_data = get_gallery_items_data($media_ids);
    if (empty($gallery_items_data)) {
        return json_encode(['error' => 'No gallery items data found']);
    }

    // Step 3: Build the dynamic elements array
    $dynamic_elements = build_dynamic_elements_array($gallery_items_data);
    if (empty($dynamic_elements)) {
        return json_encode(['error' => 'No dynamic elements found']);
    }

    // Step 4: Initialize lgSettings from $attributes
    $lgSettings = isset($attributes['lgSettings']) ? $attributes['lgSettings'] : [];

    // Step 5: Modify lgSettings if initialLayout is "inline"
    if (isset($attributes['initialLayout']) && $attributes['initialLayout'] == "inline") {
        $lgSettings['container'] = $container_class;
    }

    // Step 6: Add dynamic elements to lgSettings if dynamic is true
    if (isset($lgSettings['dynamic']) && $lgSettings['dynamic']) {
        $lgSettings['dynamicEl'] = $dynamic_elements;
    }

    // Step 7: Get the plugins array
    $plugins = build_plugins_json($attributes);

    // Step 8: Add plugins to lgSettings
    if (!empty($plugins)) {
        $lgSettings['plugins'] = $plugins;
    }

    // Step 9: Return the modified lgSettings object as JSON
    $json = json_encode($lgSettings);

    // Step 10: Check for JSON encoding errors
    if ($json === false) {
        return json_encode(['error' => 'JSON encoding failed', 'error_details' => json_last_error_msg()]);
    }

    return $json;
}



// Build the gallery styles based on $attributes and a unique class for rendering multiple galleries on the same page
function build_gallery_styles($attributes, $unique_class) {
    // Extract background color and item spacing from attributes
    $thumbs_background_color = isset($attributes['thumbsBackgroundColor']) ? esc_attr($attributes['thumbs_background_color']) : '#000000'; // Default to black if not set
    $backdrop_background_color = isset($attributes['backdropBackgroundColor']) ? esc_attr($attributes['backdropBackgroundColor']) : '#000000'; // Default to black if not set
    $item_spacing = isset($attributes['item_spacing']) ? esc_attr($attributes['item_spacing']) : '10px'; // Default spacing if not set

    // Start generating styles
    $styles = "<style>";

    // Gallery container styles
    $styles .= "
    .$unique_class {
        background-color: $background_color;
        display: flex;
        flex-wrap: wrap;
        gap: $item_spacing;
        justify-content: center;
    }";

    // LightGallery thumbnail styles
    $styles .= "
    .$unique_class .lg-thumb-outer {
        background-color: $thumbs_background_color
    }";

    $styles .= "
    .$unique_class .lg-backdrop {
        background-color: $backdrop_background_color
    }";

    // Close the style tag
    $styles .= "</style>";

    // Return the generated styles
    return $styles;
}


// Render the block
function render_lcp_gallery_block($attributes) {

    $media_ids = get_media_ids($attributes);
    // Check if any Media IDs are present 
        // If not, return null
        // Later, more logic will be needed to verify if there are any gallery items from other sources
    if ($media_ids) {
    // Generate a unique class for each gallery
    $unique_class = lcp_random_string(12, true);
    // Get the media IDs based on the attributes
    $media_ids = get_media_ids($attributes);
    
    // Get the gallery items data using the media IDs
    $gallery_items_data = get_gallery_items_data($media_ids);

    // Generate the HTML for the gallery items
    $gallery_items_html = build_gallery_items_html($gallery_items_data, $attributes);

    // Generate the gallery settings JSON
    $gallery_settings_json = build_gallery_settings_json($attributes,$unique_class);
    


    
    // Generate styles for the gallery based on the unique class
    $classes = 'lcp-gallery '; // Start with lcp-gallery class
    $classes .= $unique_class;

    // Check if 'initialLayout' is set to 'grid' and add grid column classes if applicable
    if (isset($attributes['initialLayout']) && $attributes['initialLayout'] === 'grid') {
        // Image aspect ratios
        $classes .= ' aspect-' . esc_attr($attributes['itemsAspectRatio']);
        // Grid classes
        $classes .= ' grid';
        // Grid columns
        if (isset($attributes['gridColumnsLarge'])) {
            $classes .= ' large-' . esc_attr($attributes['gridColumnsLarge']) . '-columns';
        }
        if (isset($attributes['gridColumnsMedium'])) {
            $classes .= ' medium-' . esc_attr($attributes['gridColumnsMedium']) . '-columns';
        }
        if (isset($attributes['gridColumnsSmall'])) {
            $classes .= ' small-' . esc_attr($attributes['gridColumnsSmall']) . '-columns';
        }
    }

    // Add 'initialLayout' class if it exists and isn't 'grid'
    if (isset($attributes['initialLayout']) && !empty($attributes['initialLayout']) && $attributes['initialLayout'] !== 'grid') {
        $classes .= ' ' . "lcp-inline-gallery";
    }


    // Build the styles using the unique class (if necessary)
    $styles = build_gallery_styles($attributes, $unique_class);

    // Return the complete gallery HTML with the unique class and the settings as a JSON string
    return "
        <div class= '{$classes}'  data-lgSettings='" . esc_attr($gallery_settings_json) . "'>
            {$gallery_items_html}
        </div>"; }
    else {
        return null;
    }
}
/* Initialize Gallery Block */
function lcp_gallery_block_init() {
	register_block_type( __DIR__ . '/build', array(
    'render_callback' => 'render_lcp_gallery_block',
    ));

}
add_action( 'init', 'lcp_gallery_block_init' );

/* Set Block Flag for Dynamic Enqueue */


/* Enqueue scripts and styles */
function enqueue_lightgallery_scripts() {
      // Enqueue styles
      wp_enqueue_style('lightgallery-css', get_template_directory_uri() . '/includes/blocks/lcp-gallery/assets/css/lightgallery-bundle.min.css');
      wp_enqueue_style('lg-transitions-css', get_template_directory_uri() . '/includes/blocks/lcp-gallery/assets/css/lg-transitions.css');

      // Enqueue scripts
      wp_enqueue_script('lightgallery-js', get_template_directory_uri() . '/includes/blocks/lcp-gallery/assets/js/lightgallery.min.js', array(), null, true);
      wp_enqueue_script('lg-autoplay', get_template_directory_uri() . '/includes/blocks/lcp-gallery/assets/js/lg-autoplay.min.js', array('lightgallery-js'), null, true);
      wp_enqueue_script('lg-comment', get_template_directory_uri() . '/includes/blocks/lcp-gallery/assets/js/lg-comment.min.js', array('lightgallery-js'), null, true);
      wp_enqueue_script('lg-fullscreen', get_template_directory_uri() . '/includes/blocks/lcp-gallery/assets/js/lg-fullscreen.min.js', array(), null, true);
      wp_enqueue_script('lg-hash', get_template_directory_uri() . '/includes/blocks/lcp-gallery/assets/js/lg-hash.min.js', array('lightgallery-js'), null, true);
      wp_enqueue_script('lg-medium-zoom', get_template_directory_uri() . '/includes/blocks/lcp-gallery/assets/js/lg-medium-zoom.min.js', array('lightgallery-js'), null, true);
      wp_enqueue_script('lg-pager', get_template_directory_uri() . '/includes/blocks/lcp-gallery/assets/js/lg-pager.min.js', array('lightgallery-js'), null, true);
      wp_enqueue_script('lg-relative-caption', get_template_directory_uri() . '/includes/blocks/lcp-gallery/assets/js/lg-relative-caption.min.js', array('lightgallery-js'), null, true);
      wp_enqueue_script('lg-rotate', get_template_directory_uri() . '/includes/blocks/lcp-gallery/assets/js/lg-rotate.min.js', array('lightgallery-js'), null, true);
      wp_enqueue_script('lg-share', get_template_directory_uri() . '/includes/blocks/lcp-gallery/assets/js/lg-share.min.js', array('lightgallery-js'), null, true);
      wp_enqueue_script('lg-thumbnail', get_template_directory_uri() . '/includes/blocks/lcp-gallery/assets/js/lg-thumbnail.min.js', array('lightgallery-js'), null, true);
      wp_enqueue_script('lg-video', get_template_directory_uri() . '/includes/blocks/lcp-gallery/assets/js/lg-video.min.js', array('lightgallery-js'), null, true);
          wp_enqueue_script('lg-zoom', get_template_directory_uri() . '/includes/blocks/lcp-gallery/assets/js/lg-zoom.min.js', array('lightgallery-js'), null, true);

      // Check for plugins and enqueue if necessary
      //if ( in_array( 'lg_zoom', $lcp_gallery_enqueue_data['plugins'], true ) ) {
        //  wp_enqueue_script('lg-zoom', get_template_directory_uri() . '/blocks/lcp-gallery/assets/js/lg-zoom.min.js', array('lightgallery-js'), null, true);
     // }
  }


add_action('wp_enqueue_scripts', 'enqueue_lightgallery_scripts');






/* REST */
add_action('rest_api_init', function () {
    // Register a custom route
    register_rest_route('custom/v1', '/get-gallery-supported-plugins-data', [
        'methods' => 'GET',
        'callback' => 'get_gallery_supported_plugins_data',
        'permission_callback' => '__return_true',  // Publicly accessible
    ]);
});

// Callback function to get gallery supported plugin data
function get_gallery_supported_plugins_data() {
    // Check if Jet Engine is active
    if ( ! class_exists( 'Jet_Engine' ) ) {
        return rest_ensure_response( [ 'jetengine_active' => false ] );
    }

    global $wpdb;
    $post_types = [];

    // Query to get all rows with 'content-type' status
    $results = $wpdb->get_results( "
        SELECT * FROM {$wpdb->prefix}jet_post_types
    
    " );

    // Loop through each row
    foreach ( $results as $row ) {
        // Unserialize the 'args' column to get the post type details
        $args = maybe_unserialize( $row->args );
        $meta_fields = maybe_unserialize( $row->meta_fields );

        // Get the slug value (used for related_table)
        $related_table = isset( $args['slug'] ) ? $args['slug'] : '';

        // Initialize the post type array
        $post_type_data = [
            'status' => $row->status,
            'args' => $args,
            'gallery_fields' => [],
            'related_table' => $related_table, // Add related_table with slug value
        ];

        // If there are meta_fields, filter out the gallery fields
        if ( isset( $meta_fields ) && is_array( $meta_fields ) ) {
            foreach ( $meta_fields as $field ) {
                if ( isset( $field['type'] ) && $field['type'] === 'gallery' ) {
                    $post_type_data['meta_fields'][] = $field;
                }
            }
        }

        // Add the post type to the array if gallery fields exist
        if ( ! empty( $post_type_data['meta_fields'] ) ) {
            $post_types[] = $post_type_data;
        }
    }

    return rest_ensure_response( [
        'jetengine_active' => true,
        'post_types' => $post_types,
    ] );
}

/* GALLERY CPT */
function create_lcp_gallery_cpt() {
    $labels = array(
        'name'               => 'Galleries',
        'singular_name'      => 'Gallery',
        'menu_name'          => 'Galleries',
        'name_admin_bar'     => 'Gallery',
        'add_new'            => 'Add New',
        'add_new_item'       => 'Add New Gallery',
        'new_item'           => 'New LCP Gallery',
        'edit_item'          => 'Edit LCP Gallery',
        'view_item'          => 'View LCP Gallery',
        'all_items'          => 'All LCP Galleries',
        'search_items'       => 'Search LCP Galleries',
        'parent_item_colon'  => 'Parent LCP Galleries:',
        'not_found'          => 'No LCP Galleries found.',
        'not_found_in_trash' => 'No LCP Galleries found in Trash.',
    );

    $args = array(
        'labels'             => $labels,
        'public'             => true, // Makes it public on the front end
        'has_archive'        => true, // Enables the archive page
        'show_in_rest'       => true, // Enables support for the block editor (Gutenberg)
        'rewrite'            => array( 'slug' => 'lcpgallery' ), // Set the custom slug
        'supports'           => array( 'title', 'editor', 'thumbnail', 'excerpt', 'custom-fields' ), // Post type features
        'menu_icon'          => 'dashicons-images-alt2', // Optional icon for admin menu
        'show_in_menu'       => true, // Show it in the admin menu
        'show_ui'            => true, // Ensure it shows in the WordPress admin
        'hierarchical'       => false, // Set to true for hierarchical post type (like Pages)
    );

    // Register the custom post type
    register_post_type( 'lcpgallery', $args );
}

// Hook into the 'init' action to register the custom post type
add_action( 'init', 'create_lcp_gallery_cpt' );
