<?php
/**
 * Name: Custom Image Sizes
 * Description: Add, edit, and manage custom image thumbnail sizes beyond WordPress defaults for specific design needs like hero banners, gallery thumbnails, or layout requirements
 * Category: Media
 * Icon: -
 * UseCases: [
 *   {
 *     "title": "Custom Theme Requirements",
 *     "description": "Create exact 450x300px hero images for custom theme instead of relying on medium/large sizes that don't match your design specs."
 *   },
 *   {
 *     "title": "Social Media Optimization",
 *     "description": "Generate 1200x630px images for Facebook Open Graph and Twitter Cards to ensure perfect social share previews without cropping."
 *   },
 *   {
 *     "title": "Responsive Design Breakpoints",
 *     "description": "Add image sizes matching your CSS breakpoints (mobile: 375px, tablet: 768px, desktop: 1200px) for optimal performance across devices."
 *   }
 * ]
 * Added: 2025-07-14
 * Tags: images, sizes, thumbnails, custom, dimensions
 * WhereToFind: {
 *   "location": "Configure in module settings",
 *   "url": "",
 *   "instructions": "Create custom image sizes - they appear when inserting images",
 *   "newTab": false
 * }
 */

// Prevent direct access
if (!defined('ABSPATH')) exit;

class SwitchboardCustomImageSizes {
    
    public function __construct() {
        // Register image sizes immediately when module is loaded
        $this->register_custom_sizes();

        // Also hook to after_setup_theme for additional safety
        add_action('after_setup_theme', [$this, 'register_custom_sizes']);
        add_action('wp_ajax_switchboard_save_image_size', [$this, 'ajax_save_image_size']);
        add_action('wp_ajax_switchboard_delete_image_size', [$this, 'ajax_delete_image_size']);
    }

    public function register_custom_sizes() {
        $custom_sizes = get_option('switchboard_custom_image_sizes', []);

        if (!empty($custom_sizes) && is_array($custom_sizes)) {
            foreach ($custom_sizes as $size) {
                if (!is_array($size)) {
                    continue;
                }
                if (!isset($size['name'], $size['width'], $size['height'], $size['crop'])) {
                    continue;
                }

                add_image_size(
                    $size['name'],
                    $size['width'],
                    $size['height'],
                    $size['crop']
                );
            }
        }
    }
    
    public function ajax_save_image_size() {
        check_ajax_referer('switchboard_settings', 'nonce');

        if (!current_user_can('manage_options')) {
            wp_send_json_error(['message' => __('Unauthorized', 'wpswitchboard')]);
        }

        $name = isset($_POST['name']) ? sanitize_key($_POST['name']) : '';
        $width = isset($_POST['width']) ? intval($_POST['width']) : 0;
        $height = isset($_POST['height']) ? intval($_POST['height']) : 0;
        $crop = isset($_POST['crop']) ? filter_var(wp_unslash($_POST['crop']), FILTER_VALIDATE_BOOLEAN) : false;

        if (empty($name)) {
            wp_send_json_error(['message' => __('Size name is required', 'wpswitchboard')]);
        }

        if ($width <= 0 && $height <= 0) {
            wp_send_json_error(['message' => __('Width or height must be greater than 0', 'wpswitchboard')]);
        }

        // Check if name is reserved
        $reserved = ['thumbnail', 'medium', 'medium_large', 'large', 'full'];
        if (in_array($name, $reserved, true)) {
            wp_send_json_error(['message' => __('This is a WordPress default size. Use Settings → Media to modify it.', 'wpswitchboard')]);
        }
        
        $custom_sizes = get_option('switchboard_custom_image_sizes', []);

        if (!is_array($custom_sizes)) {
            $custom_sizes = [];
        }

        // Check if size already exists
        $exists = false;
        foreach ($custom_sizes as $key => $size) {
            if (!is_array($size) || !isset($size['name'])) {
                continue;
            }
            if ($size['name'] === $name) {
                $custom_sizes[$key] = [
                    'name' => $name,
                    'width' => $width,
                    'height' => $height,
                    'crop' => $crop
                ];
                $exists = true;
                break;
            }
        }
        
        if (!$exists) {
            $custom_sizes[] = [
                'name' => $name,
                'width' => $width,
                'height' => $height,
                'crop' => $crop
            ];
        }
        
        update_option('switchboard_custom_image_sizes', $custom_sizes);

        wp_send_json_success([
            'message' => $exists ? __('Image size updated', 'wpswitchboard') : __('Image size added', 'wpswitchboard'),
            'sizes' => $custom_sizes
        ]);
    }

    public function ajax_delete_image_size() {
        check_ajax_referer('switchboard_settings', 'nonce');

        if (!current_user_can('manage_options')) {
            wp_send_json_error(['message' => __('Unauthorized', 'wpswitchboard')]);
        }

        $name = isset($_POST['name']) ? sanitize_key($_POST['name']) : '';
        $custom_sizes = get_option('switchboard_custom_image_sizes', []);
        
        $custom_sizes = array_filter($custom_sizes, function($size) use ($name) {
            return $size['name'] !== $name;
        });
        
        $custom_sizes = array_values($custom_sizes); // Re-index array

        update_option('switchboard_custom_image_sizes', $custom_sizes);

        wp_send_json_success([
            'message' => __('Image size deleted', 'wpswitchboard'),
            'sizes' => $custom_sizes
        ]);
    }

    /**
     * Render settings panel for Custom Image Sizes
     * 
     * Displays comprehensive interface for managing custom WordPress image sizes with:
     * - Display of WordPress default sizes (Thumbnail, Medium, Large) with links to Settings → Media
     * - Display of theme/plugin registered sizes (non-editable, informational)
     * - Management table for user-defined custom sizes with Edit and Delete actions
     * - Add new size form with name, width, height, and crop option inputs
     * - Real-time AJAX operations for adding, editing, and deleting sizes without page reload
     * - Input validation ensuring proper naming conventions and dimension requirements
     * - Responsive table layouts with proper styling and user feedback
     * 
     * The interface queries WordPress's $_wp_additional_image_sizes global to display all
     * currently registered image sizes across the system. Custom sizes are stored in the
     * 'switchboard_custom_image_sizes' option and registered via add_image_size(). The
     * JavaScript handles all AJAX communications for CRUD operations, with inline editing
     * capability that auto-populates the form. Size names must use lowercase letters,
     * numbers, and underscores only. Validation prevents conflicts with WordPress default
     * size names. After adding/modifying sizes, users should run the Regenerate Thumbnails
     * tool to apply changes to existing images. This module provides full lifecycle
     * management for custom image dimensions tailored to specific theme requirements.
     * 
     * @param array $settings Current module settings (not used - sizes stored separately in switchboard_custom_image_sizes option)
     * @return void Outputs HTML directly
     */
    public function render_settings($settings = []) {
        $custom_sizes = get_option('switchboard_custom_image_sizes', []);
        
        // Get theme/plugin registered sizes
        global $_wp_additional_image_sizes;
        $theme_sizes = [];
        if (!empty($_wp_additional_image_sizes)) {
            foreach ($_wp_additional_image_sizes as $name => $size_data) {
                $theme_sizes[] = [
                    'name' => $name,
                    'width' => $size_data['width'],
                    'height' => $size_data['height'],
                    'crop' => $size_data['crop']
                ];
            }
        }
        
        $html = '
            <style>
                /* Show action buttons on card hover for custom image sizes */
                #custom-sizes-list .sb-sp-card:hover .category-actions,
                #custom-sizes-list .category-actions:hover {
                    opacity: 1 !important;
                    pointer-events: auto !important;
                }
            </style>
            <input type="hidden" name="module" value="custom-image-sizes">

            <div class="sb-sp-group" style="margin-bottom: 24px;">
                <h3 class="sb-sp-heading">' . esc_html__('Custom Image Sizes', 'wpswitchboard') . '</h3>
                <p class="sb-sp-description">' . esc_html__('Add custom image sizes that will be automatically generated when images are uploaded.', 'wpswitchboard') . '</p>
            </div>

            <div class="sb-sp-info-box sb-sp-info-box-tip" style="margin-bottom: 24px;">
                <h4 class="sb-sp-heading-sm">' . esc_html__('Important Note', 'wpswitchboard') . '</h4>
                <p class="sb-sp-description" style="margin: 0;">' . esc_html__('After adding/modifying sizes, use the Regenerate Thumbnails tool to apply changes to existing images.', 'wpswitchboard') . '</p>
            </div>

            <div class="sb-sp-info-box sb-sp-info-box-info" style="margin-bottom: 24px;">
                <h4 class="sb-sp-heading-sm">' . esc_html__('WordPress Default Sizes', 'wpswitchboard') . '</h4>
                <p class="sb-sp-description" style="margin: 0 0 12px 0;">' .
                // translators: %s is a link to the WordPress Settings Media page
                sprintf(esc_html__('These are managed in %s', 'wpswitchboard'), '<a href="' . admin_url('options-media.php') . '" target="_blank" style="color: var(--primary-700); text-decoration: underline;">' . esc_html__('Settings → Media', 'wpswitchboard') . '</a>') . '</p>
                <div style="display: flex; flex-direction: column; gap: 8px;">
                    <div style="display: flex; justify-content: space-between; align-items: center; padding: 8px 0; border-bottom: 1px solid var(--primary-100);">
                        <strong>' . esc_html__('Thumbnail', 'wpswitchboard') . '</strong>
                        <span style="color: #64748b; font-size: 13px;">' . get_option('thumbnail_size_w') . ' × ' . get_option('thumbnail_size_h') . ' px</span>
                    </div>
                    <div style="display: flex; justify-content: space-between; align-items: center; padding: 8px 0; border-bottom: 1px solid var(--primary-100);">
                        <strong>' . esc_html__('Medium', 'wpswitchboard') . '</strong>
                        <span style="color: #64748b; font-size: 13px;">' . get_option('medium_size_w') . ' × ' . get_option('medium_size_h') . ' px</span>
                    </div>
                    <div style="display: flex; justify-content: space-between; align-items: center; padding: 8px 0;">
                        <strong>' . esc_html__('Large', 'wpswitchboard') . '</strong>
                        <span style="color: #64748b; font-size: 13px;">' . get_option('large_size_w') . ' × ' . get_option('large_size_h') . ' px</span>
                    </div>
                </div>
            </div>';

        if (!empty($theme_sizes)) {
            $html .= '
            <div class="sb-sp-info-box sb-sp-info-box-info" style="margin-bottom: 24px;">
                <h4 class="sb-sp-heading-sm">' . esc_html__('Theme/Plugin Registered Sizes', 'wpswitchboard') . '</h4>
                <p class="sb-sp-description" style="margin: 0 0 12px 0;">' . esc_html__('These sizes are registered by your theme or plugins. They cannot be edited here.', 'wpswitchboard') . '</p>
                <div style="display: flex; flex-direction: column; gap: 8px;">';
            
            foreach ($theme_sizes as $size) {
                $html .= '<div style="display: flex; justify-content: space-between; align-items: center; padding: 8px 0; border-bottom: 1px solid var(--primary-100);">
                    <strong>' . esc_html($size['name']) . '</strong>
                    <span style="color: #64748b; font-size: 13px;">' . $size['width'] . ' × ' . $size['height'] . ' px ' . ($size['crop'] ? '(cropped)' : '') . '</span>
                </div>';
            }
            
            $html .= '</div>
            </div>';
        }

        $html .= '
            <div class="sb-sp-group" style="margin-bottom: 24px;">
                <h3 class="sb-sp-heading">' . esc_html__('Your Custom Sizes', 'wpswitchboard') . '</h3>
                <p class="sb-sp-description">' . esc_html__('Add custom image sizes for your theme or specific use cases.', 'wpswitchboard') . '</p>

                <div id="custom-sizes-list" style="display: flex; flex-direction: column; gap: 12px; margin-top: 16px;">
                    ' . (empty($custom_sizes) ? '<div class="sb-sp-card" style="box-shadow: none !important; border: 1px solid #e5e7eb;"><p class="sb-sp-description" style="margin: 0; padding: 20px; text-align: center;"><em>' . esc_html__('No custom sizes yet. Add one below!', 'wpswitchboard') . '</em></p></div>' : '') . '
                </div>
            </div>

            <div class="sb-sp-group">
                <h3 class="sb-sp-heading">➕ ' . esc_html__('Add New Image Size', 'wpswitchboard') . '</h3>
                
                <div class="sb-sp-card sb-sp-p-4" style="margin-bottom: 16px;">
                    <div class="sb-sp-group sb-sp-field-horizontal" style="margin-bottom: 16px;">
                        <div class="sb-sp-field-horizontal-left">
                            <label for="new_size_name" class="sb-sp-label">' . esc_html__('Size Name', 'wpswitchboard') . '</label>
                            <p class="sb-sp-description">' . esc_html__('Use lowercase letters, numbers, and underscores only (e.g., product_thumb, hero_banner)', 'wpswitchboard') . '</p>
                        </div>
                        <input type="text" id="new_size_name" class="sb-sp-input" placeholder="' . esc_attr__('e.g., hero_image', 'wpswitchboard') . '">
                    </div>

                    <div class="sb-sp-group sb-sp-field-horizontal" style="margin-bottom: 16px;">
                        <div class="sb-sp-field-horizontal-left">
                            <label for="new_size_width" class="sb-sp-label">' . esc_html__('Width (px)', 'wpswitchboard') . '</label>
                            <p class="sb-sp-description">' . esc_html__('Set to 0 for proportional width', 'wpswitchboard') . '</p>
                        </div>
                        <input type="number" id="new_size_width" class="sb-sp-input" value="800" min="0" max="10000" style="width: 150px;">
                    </div>

                    <div class="sb-sp-group sb-sp-field-horizontal" style="margin-bottom: 16px;">
                        <div class="sb-sp-field-horizontal-left">
                            <label for="new_size_height" class="sb-sp-label">' . esc_html__('Height (px)', 'wpswitchboard') . '</label>
                            <p class="sb-sp-description">' . esc_html__('Set to 0 for proportional height', 'wpswitchboard') . '</p>
                        </div>
                        <input type="number" id="new_size_height" class="sb-sp-input" value="600" min="0" max="10000" style="width: 150px;">
                    </div>

                    <div class="sb-module-option-item sb-module-toggle-item" style="margin-bottom: 0;">
                        <div class="sb-module-option-content">
                            <div class="sb-module-toggle-header">
                                <strong class="sb-module-option-title">' . esc_html__('Crop to Exact Dimensions', 'wpswitchboard') . '</strong>
                                <label class="sb-module-toggle">
                                    <input type="checkbox"
                                           id="new_size_crop"
                                           value="1">
                                    <span class="sb-module-toggle-slider"></span>
                                </label>
                            </div>
                            <p class="sb-module-option-text">' . esc_html__('Crop images to exact dimensions (may cut off parts of image)', 'wpswitchboard') . '</p>
                            <p class="sb-sp-description" style="margin-top: 8px;">
                                <strong>' . esc_html__('Unchecked:', 'wpswitchboard') . '</strong> ' . esc_html__('Images fit within dimensions, maintaining aspect ratio', 'wpswitchboard') . '<br>
                                <strong>' . esc_html__('Checked:', 'wpswitchboard') . '</strong> ' . esc_html__('Images cropped to exact dimensions', 'wpswitchboard') . '
                            </p>
                        </div>
                    </div>
                </div>

                <div class="sb-sp-button-group" style="justify-content: flex-end;">
                    <button type="button" id="add-image-size" class="button button-primary button-small">
                        <span class="dashicons dashicons-plus-alt" style="margin-top: 3px;"></span> ' . esc_html__('Add Image Size', 'wpswitchboard') . '
                    </button>
                </div>
            </div>
            
            <script>
            jQuery(document).ready(function($) {
                // Ensure ajaxurl is available
                var ajaxUrl = (typeof switchboardSettings !== "undefined" && switchboardSettings.ajaxurl)
                    ? switchboardSettings.ajaxurl
                    : "' . admin_url('admin-ajax.php') . '";

                var customSizes = ' . json_encode($custom_sizes) . ';

                function renderSizes() {
                    if (customSizes.length === 0) {
                        $("#custom-sizes-list").html("<div class=\"sb-sp-card\" style=\"box-shadow: none !important; border: 1px solid #e5e7eb;\"><p class=\"sb-sp-description\" style=\"margin: 0; padding: 20px; text-align: center;\"><em>No custom sizes yet. Add one below!</em></p></div>");
                        return;
                    }
                    
                    var html = "";
                    $.each(customSizes, function(i, size) {
                        var dimensions = size.width + " × " + size.height + " px";
                        if (size.width == 0 && size.height == 0) {
                            dimensions = "<em>Full Size</em>";
                        } else if (size.width == 0) {
                            dimensions = "Auto × " + size.height + " px";
                        } else if (size.height == 0) {
                            dimensions = size.width + " × Auto px";
                        }
                        
                        html += \'<div class="sb-sp-card" style="box-shadow: none !important; border: 1px solid #e5e7eb; position: relative;">\';
                        html += \'<div style="padding: 8px 12px;">\';
                        html += \'<div style="display: flex; justify-content: space-between; align-items: center; gap: 12px;">\';
                        html += \'<div style="flex: 1; min-width: 0;">\';
                        html += \'<strong class="sb-sp-text-semibold" style="display: block; margin-bottom: 4px; color: #1e293b;">\' + size.name + \'</strong>\';
                        html += \'<span style="font-size: 13px; color: #64748b;">\' + dimensions + (size.crop ? \' <span style="color: var(--primary-700);">(cropped)</span>\' : \'\') + \'</span>\';
                        html += \'</div>\';
                        html += \'<div style="display: flex; align-items: center; gap: 8px; flex-shrink: 0; position: relative;">\';
                        html += \'<div class="sb-sp-button-group category-actions" style="margin-top: 0; gap: 6px; opacity: 0; transition: opacity 0.15s ease; pointer-events: none;">\';
                        html += \'<button type="button" class="sb-sp-card-action-btn sb-sp-card-action-btn-edit edit-size" data-name="\' + size.name + \'" data-width="\' + size.width + \'" data-height="\' + size.height + \'" data-crop="\' + size.crop + \'" style="pointer-events: auto;">Edit</button>\';
                        html += \'<button type="button" class="sb-sp-card-action-btn sb-sp-card-action-btn-delete delete-size" data-name="\' + size.name + \'" style="pointer-events: auto;">Delete</button>\';
                        html += \'</div>\';
                        html += \'</div>\';
                        html += \'</div>\';
                        html += \'</div>\';
                        html += \'</div>\';
                    });
                    
                    $("#custom-sizes-list").html(html);
                }
                
                renderSizes();
                
                $("#add-image-size").on("click", function() {
                    var name = $("#new_size_name").val().trim();
                    var width = parseInt($("#new_size_width").val());
                    var height = parseInt($("#new_size_height").val());
                    var crop = $("#new_size_crop").is(":checked");
                    
                    if (!name) {
                        alert("Please enter a size name");
                        return;
                    }
                    
                    if (!/^[a-z0-9_]+$/.test(name)) {
                        alert("Size name can only contain lowercase letters, numbers, and underscores");
                        return;
                    }
                    
                    if (width <= 0 && height <= 0) {
                        alert("Width or height must be greater than 0");
                        return;
                    }
                    
                    $.ajax({
                        url: ajaxUrl,
                        type: "POST",
                        data: {
                            action: "switchboard_save_image_size",
                            nonce: "' . wp_create_nonce('switchboard_settings') . '",
                            name: name,
                            width: width,
                            height: height,
                            crop: crop
                        },
                        success: function(response) {
                            if (response.success) {
                                customSizes = response.data.sizes;
                                renderSizes();
                                $("#new_size_name").val("");
                                $("#new_size_width").val("800");
                                $("#new_size_height").val("600");
                                $("#new_size_crop").prop("checked", false);
                                alert(response.data.message + "\\n\\nDon\'t forget to regenerate thumbnails for existing images!");
                            } else {
                                alert("Error: " + response.data.message);
                            }
                        }
                    });
                });
                
                $(document).on("click", ".edit-size", function() {
                    var name = $(this).data("name");
                    var width = $(this).data("width");
                    var height = $(this).data("height");
                    var crop = $(this).data("crop");
                    
                    $("#new_size_name").val(name);
                    $("#new_size_width").val(width);
                    $("#new_size_height").val(height);
                    $("#new_size_crop").prop("checked", crop);
                    
                    $("html, body").animate({ scrollTop: $("#new_size_name").offset().top - 100 }, 500);
                    $("#new_size_name").focus();
                });
                
                $(document).on("click", ".delete-size", function() {
                    var name = $(this).data("name");
                    
                    if (!confirm("Delete image size \\"" + name + "\\"?\\n\\nExisting thumbnails will not be deleted, but this size will not be generated for new uploads.")) {
                        return;
                    }
                    
                    $.ajax({
                        url: ajaxUrl,
                        type: "POST",
                        data: {
                            action: "switchboard_delete_image_size",
                            nonce: "' . wp_create_nonce('switchboard_settings') . '",
                            name: name
                        },
                        success: function(response) {
                            if (response.success) {
                                customSizes = response.data.sizes;
                                renderSizes();
                                alert(response.data.message);
                            } else {
                                alert("Error: " + response.data.message);
                            }
                        }
                    });
                });
            });
            </script>
        ';
        
        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is built safely with proper escaping throughout
        echo $html;
    }

    /**
     * Register data locations for cleanup system
     *
     * @return array Data storage locations
     */
    public function register_data_locations() {
        return [
            'options' => [
                'switchboard_custom_image_sizes',
            ],
            'option_patterns' => [],
            'tables' => [],
            'post_meta' => [],
            'user_meta' => [],
        ];
    }
}

// Initialize and register with data system
$switchboard_instance = new SwitchboardCustomImageSizes();
Switchboard_Data_Registry::get_instance()->auto_register($switchboard_instance, __FILE__);
