<?php

/**
 * JCOGS Image Pro - Rounded Corners Parameter Package
 * ==================================================
 * Sophisticated form interface for rounded corners parameter
 * 
 * @category   ExpressionEngine Add-on
 * @package    JCOGS Image Pro
 * @author     JCOGS Design <contact@jcogs.net>
 * @copyright  Copyright (c) 2021 - 2025 JCOGS Design
 * @license    https://jcogs.net/add-ons/license/jcogs_img_pro
 * @version    2.0.6
 * @link       https://JCOGS.net/
 * @since      Parameter Package Implementation
 */

namespace JCOGSDesign\JCOGSImagePro\Service\ParameterPackages;

/**
 * Rounded Corners Parameter Package
 * 
 * Provides sophisticated 5-field interface for rounded corners parameter instead of requiring
 * users to construct complex pipe-separated parameter strings manually.
 * 
 * Rounded Corners Parameter Format (from JCOGS documentation):
 * rounded_corners="[all|tl|tr|bl|br],<integer>[,<colour>]…"
 * 
 * Examples:
 * - rounded_corners="all,20" - 20px radius on all corners
 * - rounded_corners="tl,20|br,40px|tr,25%" - Different radius for different corners
 * - rounded_corners="all,20px|br,30%" - Set all corners to 20px, then override bottom-right to 30%
 * 
 * Documentation: https://jcogs.net/documentation/jcogs_img/jcogs_img-parameters#jcogs-image-parameter-rounded-corners
 */
class RoundedCornersParameterPackage extends AbstractParameterPackage
{
    /**
     * Package identifier
     * 
     * @return string Package name
     */
    public function getName(): string 
    {
        return 'rounded_corners_parameter_package';
    }

    /**
     * Get the display label for this parameter package
     * 
     * @return string Package label
     */
    public function getLabel(): string
    {
        return 'Rounded Corners Parameters';
    }

    /**
     * Get the description for this parameter package
     * 
     * @return string Package description
     */
    public function getDescription(): string
    {
        return 'Corner radius controls for rounded corner effects on images';
    }

    /**
     * Get the category for this parameter package
     * 
     * @return string Package category
     */
    public function getCategory(): string
    {
        return 'transformational';
    }

    /**
     * Parameters handled by this package
     * 
     * @return array List of parameter names
     */
    public function getParameters(): array 
    {
        return ['rounded_corners'];
    }

    /**
     * Priority for rounded corners parameter package
     * Higher priority than general transformational package
     * 
     * @return int Priority order (lower numbers = higher priority)
     */
    public function getPriority(): int
    {
        return 23; // Higher than TransformationalParameterPackage (20)
    }

    /**
     * Parse composite string supporting both named and positional formats
     * 
     * Named format (NEW): "all:20px|all_color:#FFF|tl:30"
     * Positional format (LEGACY): "all,20px|tl,30,#FFF" (radius,color in same segment)
     * 
     * @param string $param_name Parameter name (should be 'rounded_corners')
     * @param string $value Parameter value to parse
     * @return array Parsed sub-parameters with separate radius and color keys
     */
    public function parseCompositeString(string $param_name, string $value): array
    {
        // Default structure - separate radius and color for each corner
        $defaults = [
            'corner_all_radius' => '',
            'corner_all_color' => '',
            'corner_tl_radius' => '',
            'corner_tl_color' => '',
            'corner_tr_radius' => '',
            'corner_tr_color' => '',
            'corner_bl_radius' => '',
            'corner_bl_color' => '',
            'corner_br_radius' => '',
            'corner_br_color' => ''
        ];
        
        if (empty($value) || !is_string($value)) {
            return $defaults;
        }
        
        // Detect format: if contains colon before first pipe, it's named format
        $is_named = $this->_is_named_format($value);
        
        if ($is_named) {
            return $this->_parse_named_format($value, $defaults);
        } else {
            return $this->_parse_positional_format($value, $defaults);
        }
    }
    
    /**
     * Get sub-parameter definitions for validation
     * 
     * Defines validation rules for each corner's radius and optional color.
     * Each corner has two sub-parameters: radius (required) and color (optional).
     * 
     * @return array Sub-parameter validation rules
     */
    public function getSubParameterDefinitions(): array
    {
        return [
            // All corners radius
            'corner_all_radius' => [
                'type' => 'dimension',
                'description' => 'Radius for all corners (e.g., 20px, 15%)',
                'required' => false,
                'example' => '20px'
            ],
            'corner_all_color' => [
                'type' => 'color',
                'description' => 'Color for all corners (optional)',
                'required' => false,
                'example' => '#FFF'
            ],
            
            // Top-left corner
            'corner_tl_radius' => [
                'type' => 'dimension',
                'description' => 'Top-left corner radius (overrides "all" if set)',
                'required' => false,
                'example' => '30px'
            ],
            'corner_tl_color' => [
                'type' => 'color',
                'description' => 'Top-left corner color (optional)',
                'required' => false,
                'example' => '#000'
            ],
            
            // Top-right corner
            'corner_tr_radius' => [
                'type' => 'dimension',
                'description' => 'Top-right corner radius (overrides "all" if set)',
                'required' => false,
                'example' => '30px'
            ],
            'corner_tr_color' => [
                'type' => 'color',
                'description' => 'Top-right corner color (optional)',
                'required' => false,
                'example' => '#FF0000'
            ],
            
            // Bottom-left corner
            'corner_bl_radius' => [
                'type' => 'dimension',
                'description' => 'Bottom-left corner radius (overrides "all" if set)',
                'required' => false,
                'example' => '25%'
            ],
            'corner_bl_color' => [
                'type' => 'color',
                'description' => 'Bottom-left corner color (optional)',
                'required' => false,
                'example' => '#00FF00'
            ],
            
            // Bottom-right corner
            'corner_br_radius' => [
                'type' => 'dimension',
                'description' => 'Bottom-right corner radius (overrides "all" if set)',
                'required' => false,
                'example' => '40px'
            ],
            'corner_br_color' => [
                'type' => 'color',
                'description' => 'Bottom-right corner color (optional)',
                'required' => false,
                'example' => '#FFF'
            ]
        ];
    }
    
    /**
     * Get form fields for rounded corners parameter
     * 
     * Creates separate radius and color fields for each corner (10 fields total).
     * Color fields include color picker support.
     * 
     * @param array $current_values Current parameter values  
     * @return array Flat associative array of form fields
     */
    protected function getPackageFormFields(array $current_values = []): array
    {
        // Get current rounded_corners value
        $current_value = $current_values['rounded_corners'] ?? '';
        
        // Parse existing rounded_corners value using new composite parser
        $parsed = $this->parseCompositeString('rounded_corners', $current_value);
        
        return [
            // All Corners - Radius
            'rounded_corners_all_radius' => [
                'type' => 'text',
                'label' => 'All Corners - Radius',
                'desc' => 'Set the same radius for all four corners (e.g., 20, 15px, 5%)',
                'value' => $parsed['corner_all_radius'] ?? '',
                'placeholder' => 'For example: 20px'
            ],
            
            // All Corners - Color
            'rounded_corners_all_color' => [
                'type' => 'text',
                'label' => 'All Corners - Color',
                'desc' => 'Optional background color for all corners. Supports hex codes, CSS rgb()/rgba(), or color names.',
                'value' => $parsed['corner_all_color'] ?? '',
                'placeholder' => 'For example: #FFF, rgb(255,255,255)',
                'attrs' => [
                    'class' => 'form-control jcogs-color-field',
                    'data-color-picker' => 'true'
                ]
            ],
            
            // Top-Left - Radius
            'rounded_corners_tl_radius' => [
                'type' => 'text',
                'label' => 'Top-Left - Radius',
                'desc' => 'Radius for the top-left corner (overrides "All Corners" if set)',
                'value' => $parsed['corner_tl_radius'] ?? '',
                'placeholder' => 'For example: 25px'
            ],
            
            // Top-Left - Color
            'rounded_corners_tl_color' => [
                'type' => 'text',
                'label' => 'Top-Left - Color',
                'desc' => 'Optional background color for top-left corner',
                'value' => $parsed['corner_tl_color'] ?? '',
                'placeholder' => 'For example: #000',
                'attrs' => [
                    'class' => 'form-control jcogs-color-field',
                    'data-color-picker' => 'true'
                ]
            ],
            
            // Top-Right - Radius
            'rounded_corners_tr_radius' => [
                'type' => 'text',
                'label' => 'Top-Right - Radius',
                'desc' => 'Radius for the top-right corner (overrides "All Corners" if set)',
                'value' => $parsed['corner_tr_radius'] ?? '',
                'placeholder' => 'For example: 25px'
            ],
            
            // Top-Right - Color
            'rounded_corners_tr_color' => [
                'type' => 'text',
                'label' => 'Top-Right - Color',
                'desc' => 'Optional background color for top-right corner',
                'value' => $parsed['corner_tr_color'] ?? '',
                'placeholder' => 'For example: #FF0000',
                'attrs' => [
                    'class' => 'form-control jcogs-color-field',
                    'data-color-picker' => 'true'
                ]
            ],
            
            // Bottom-Left - Radius
            'rounded_corners_bl_radius' => [
                'type' => 'text',
                'label' => 'Bottom-Left - Radius',
                'desc' => 'Radius for the bottom-left corner (overrides "All Corners" if set)',
                'value' => $parsed['corner_bl_radius'] ?? '',
                'placeholder' => 'For example: 25px'
            ],
            
            // Bottom-Left - Color
            'rounded_corners_bl_color' => [
                'type' => 'text',
                'label' => 'Bottom-Left - Color',
                'desc' => 'Optional background color for bottom-left corner',
                'value' => $parsed['corner_bl_color'] ?? '',
                'placeholder' => 'For example: #00FF00',
                'attrs' => [
                    'class' => 'form-control jcogs-color-field',
                    'data-color-picker' => 'true'
                ]
            ],
            
            // Bottom-Right - Radius
            'rounded_corners_br_radius' => [
                'type' => 'text',
                'label' => 'Bottom-Right - Radius',
                'desc' => 'Radius for the bottom-right corner (overrides "All Corners" if set)',
                'value' => $parsed['corner_br_radius'] ?? '',
                'placeholder' => 'For example: 25px'
            ],
            
            // Bottom-Right - Color
            'rounded_corners_br_color' => [
                'type' => 'text',
                'label' => 'Bottom-Right - Color',
                'desc' => 'Optional background color for bottom-right corner',
                'value' => $parsed['corner_br_color'] ?? '',
                'placeholder' => 'For example: #FFF',
                'attrs' => [
                    'class' => 'form-control jcogs-color-field',
                    'data-color-picker' => 'true'
                ]
            ]
        ];
    }

    /**
     * Process form data to generate rounded_corners parameter value in named attributes format
     * 
     * Generates self-documenting named format with separate radius and color attributes:
     * "all:20px|all_color:#FFF|tl:30|tl_color:#000"
     * 
     * @param string $parameter_name Parameter name (should be 'rounded_corners')
     * @param array $form_data Form submission data
     * @return string Formatted rounded_corners parameter value in named attributes format
     */
    public function processParameterFromForm(string $parameter_name, array $form_data): string 
    {
        $named_parts = [];

        // Process each corner with its radius and optional color
        $corners = [
            'all' => [
                'radius' => trim($form_data['rounded_corners_all_radius'] ?? ''),
                'color' => trim($form_data['rounded_corners_all_color'] ?? '')
            ],
            'tl' => [
                'radius' => trim($form_data['rounded_corners_tl_radius'] ?? ''),
                'color' => trim($form_data['rounded_corners_tl_color'] ?? '')
            ],
            'tr' => [
                'radius' => trim($form_data['rounded_corners_tr_radius'] ?? ''),
                'color' => trim($form_data['rounded_corners_tr_color'] ?? '')
            ],
            'bl' => [
                'radius' => trim($form_data['rounded_corners_bl_radius'] ?? ''),
                'color' => trim($form_data['rounded_corners_bl_color'] ?? '')
            ],
            'br' => [
                'radius' => trim($form_data['rounded_corners_br_radius'] ?? ''),
                'color' => trim($form_data['rounded_corners_br_color'] ?? '')
            ]
        ];

        foreach ($corners as $corner_code => $values) {
            // Only add radius if it has a value
            if (!empty($values['radius'])) {
                $named_parts[] = "{$corner_code}:{$values['radius']}";
                
                // If color is also provided, add it as separate attribute
                if (!empty($values['color'])) {
                    $named_parts[] = "{$corner_code}_color:{$values['color']}";
                }
            }
        }

        // If no corners are specified, return empty
        if (empty($named_parts)) {
            return '';
        }

        // Return pipe-separated rounded_corners parameter in named format
        return implode('|', $named_parts);
    }

    /**
     * Normalize rounded_corners parameter to positional format for filter processing
     * 
     * Converts named format to positional format that filters expect.
     * Named format: "all:20px|all_color:#FFF|tl:30"
     * Positional format: "all,20px,#FFF|tl,30"
     * 
     * @param string $value Parameter value in either format
     * @return string Normalized positional format
     */
    public function normalizeRoundedCornersParameter(string $value): string
    {
        if (empty($value)) {
            return '';
        }
        
        // Parse using format detection (returns separate radius and color keys)
        $parsed = $this->parseCompositeString('rounded_corners', $value);
        
        // Convert back to positional format
        $positional_parts = [];
        
        // Map from corner_* keys back to corner codes
        $corners = ['all', 'tl', 'tr', 'bl', 'br'];
        
        foreach ($corners as $corner_code) {
            $radius_key = "corner_{$corner_code}_radius";
            $color_key = "corner_{$corner_code}_color";
            
            $radius = $parsed[$radius_key] ?? '';
            $color = $parsed[$color_key] ?? '';
            
            if (!empty($radius)) {
                // Build positional segment: corner,radius[,color]
                if (!empty($color)) {
                    $positional_parts[] = "{$corner_code},{$radius},{$color}";
                } else {
                    $positional_parts[] = "{$corner_code},{$radius}";
                }
            }
        }
        
        return implode('|', $positional_parts);
    }

    /**
     * Detect if value uses named format
     * 
     * Named format contains colons (all:20px|tl:30)
     * Positional format uses commas (all,20px|tl,30)
     * 
     * @param string $value Value to check
     * @return bool True if named format
     */
    private function _is_named_format(string $value): bool
    {
        // Look for colon before the first pipe or end of string
        $first_pipe = strpos($value, '|');
        $first_part = $first_pipe !== false ? substr($value, 0, $first_pipe) : $value;
        
        return strpos($first_part, ':') !== false;
    }
    
    /**
     * Parse named attribute format
     * 
     * New format with separate radius and color attributes:
     * "all:20px|all_color:#FFF|tl:30|tl_color:#000"
     * 
     * Legacy named format (also supported):
     * "all:20px,#FFF|tl:30,#000" (radius,color in value)
     * 
     * @param string $value Named format string
     * @param array $defaults Default values (with _radius and _color keys)
     * @return array Parsed sub-parameters with separate radius and color
     */
    private function _parse_named_format(string $value, array $defaults): array
    {
        $result = $defaults;
        
        // Split on pipe to get each attribute
        $parts = explode('|', $value);
        
        foreach ($parts as $part) {
            $part = trim($part);
            if (empty($part)) continue;
            
            // Split on colon to separate attribute name from value
            $colon_pos = strpos($part, ':');
            if ($colon_pos === false) continue;
            
            $attribute_name = trim(substr($part, 0, $colon_pos));
            $attribute_value = trim(substr($part, $colon_pos + 1));
            
            // Check if this is a color attribute (ends with _color)
            if (str_ends_with($attribute_name, '_color')) {
                // Extract corner code (e.g., "all_color" -> "all")
                $corner_code = substr($attribute_name, 0, -6); // Remove "_color" suffix
                $corner_key = $this->_map_corner_code($corner_code);
                
                if ($corner_key !== null) {
                    $result[$corner_key . '_color'] = $attribute_value;
                }
            } else {
                // This is a radius attribute
                // Check if value contains comma (legacy format with radius,color)
                if (str_contains($attribute_value, ',')) {
                    // Split radius and color
                    list($radius, $color) = explode(',', $attribute_value, 2);
                    $radius = trim($radius);
                    $color = trim($color);
                    
                    $corner_key = $this->_map_corner_code($attribute_name);
                    if ($corner_key !== null) {
                        $result[$corner_key . '_radius'] = $radius;
                        if (!empty($color)) {
                            $result[$corner_key . '_color'] = $color;
                        }
                    }
                } else {
                    // Pure radius value
                    $corner_key = $this->_map_corner_code($attribute_name);
                    if ($corner_key !== null) {
                        $result[$corner_key . '_radius'] = $attribute_value;
                    }
                }
            }
        }
        
        return $result;
    }
    
    /**
     * Parse positional (legacy) format
     * 
     * Format: "all,20px|tl,30|br,40,#FFF"
     * Each segment: corner,radius[,color]
     * 
     * @param string $value Positional format string
     * @param array $defaults Default values (with _radius and _color keys)
     * @return array Parsed sub-parameters with separate radius and color
     */
    private function _parse_positional_format(string $value, array $defaults): array
    {
        $result = $defaults;
        
        // Split on pipe to get each corner definition
        $parts = explode('|', $value);
        
        foreach ($parts as $part) {
            $part = trim($part);
            if (empty($part)) continue;
            
            // Split on commas: corner,radius[,color]
            $comma_parts = explode(',', $part);
            if (count($comma_parts) < 2) continue;
            
            $corner = trim($comma_parts[0]);
            $radius = trim($comma_parts[1]);
            $color = isset($comma_parts[2]) ? trim($comma_parts[2]) : '';
            
            // Skip if corner or radius is empty (fixes issue #100 with ,,,)
            if (empty($corner) || empty($radius)) {
                continue;
            }
            
            // Map corner codes to result array keys
            $corner_key = $this->_map_corner_code($corner);
            if ($corner_key !== null) {
                $result[$corner_key . '_radius'] = $radius;
                if (!empty($color)) {
                    $result[$corner_key . '_color'] = $color;
                }
            }
        }
        
        return $result;
    }
    
    /**
     * Map corner code to array key
     * 
     * @param string $corner Corner code (all, tl, tr, bl, br)
     * @return string|null Mapped key or null if invalid
     */
    private function _map_corner_code(string $corner): ?string
    {
        $map = [
            'all' => 'corner_all',
            'tl' => 'corner_tl',
            'tr' => 'corner_tr',
            'bl' => 'corner_bl',
            'br' => 'corner_br'
        ];
        
        $corner_lower = strtolower($corner);
        return $map[$corner_lower] ?? null;
    }

    /**
     * Validate rounded corners parameter value
     * 
     * Accepts both named and positional formats.
     * Named format: "all:20px|all_color:#FFF|tl:30"
     * Positional format: "all,20px|tl,30,#FFF"
     * 
     * @param string $param_name Parameter name being validated
     * @param string $value Parameter value to validate
     * @return bool|string True if valid, error message if invalid
     */
    public function validateParameter(string $param_name, $value): bool|string
    {
        if ($param_name !== 'rounded_corners') {
            return parent::validateParameter($param_name, $value);
        }

        $parameter_value = (string) $value;

        // Empty rounded corners parameter is valid (no rounded corners)
        if (empty(trim($parameter_value))) {
            return true;
        }

        // Try to parse using the composite parser (handles both formats)
        try {
            $parsed = $this->parseCompositeString('rounded_corners', $parameter_value);
            
            // Validate each parsed radius and color
            $valid_corners = ['all', 'tl', 'tr', 'bl', 'br'];
            
            foreach ($valid_corners as $corner_code) {
                $radius_key = "corner_{$corner_code}_radius";
                $color_key = "corner_{$corner_code}_color";
                
                $radius = $parsed[$radius_key] ?? '';
                $color = $parsed[$color_key] ?? '';
                
                // If radius is provided, validate it
                if (!empty($radius)) {
                    if (!preg_match('/^\d+(?:px|%)?$/', $radius)) {
                        return "Radius value for '{$corner_code}' must be a number optionally followed by 'px' or '%'. Found: {$radius}";
                    }
                }
                
                // If color is provided, validate it
                if (!empty($color)) {
                    $color_clean = ltrim($color, '#');
                    
                    // Check for valid hex color (3, 4, 6, or 8 digits)
                    if (!preg_match('/^[0-9a-fA-F]{3}(?:[0-9a-fA-F]{1})?(?:[0-9a-fA-F]{2})?(?:[0-9a-fA-F]{2})?$/', $color_clean)) {
                        // Check for RGB/RGBA format
                        if (!preg_match('/^rgba?\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*(?:,\s*[\d.]+\s*)?\)$/i', $color)) {
                            // Check for color names (basic validation)
                            if (!preg_match('/^[a-z]+$/i', $color)) {
                                return "Corner color for '{$corner_code}' must be a valid hex color, CSS rgb()/rgba(), or color name. Found: {$color}";
                            }
                        }
                    }
                }
            }
            
            return true;
            
        } catch (\Exception $e) {
            return 'Failed to parse rounded_corners parameter: ' . $e->getMessage();
        }
    }
}
