<?php

/**
 * JCOGS Image Pro - Provider Filter Wrapper
 * =========================================
 * Wraps FilterProvider interface implementations as Imagine filters
 * 
 * @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      2.0.0
 */

namespace JCOGSDesign\JCOGSImagePro\Filters;

use Imagine\Filter\FilterInterface;
use Imagine\Image\ImageInterface;
use JCOGSDesign\JCOGSImagePro\Service\Provider\FilterProviderInterface;

/**
 * Provider Filter Wrapper
 * 
 * Wraps FilterProvider implementations to work within the standard
 * Imagine filter pipeline. This allows companion add-ons to register
 * custom filters that integrate seamlessly with built-in filters.
 * 
 * Provider Integration Architecture:
 * - Companion add-ons implement FilterProviderInterface
 * - Register providers via ProviderRegistry
 * - IMG Pro checks providers before built-in filters
 * - This wrapper adapts provider to Imagine's FilterInterface
 * 
 * @see FilterProviderInterface For implementing custom filters
 * @see \JCOGSDesign\JCOGSImagePro\Service\ProviderRegistry For registration
 */
class ProviderFilter implements FilterInterface
{
    /**
     * @var FilterProviderInterface The filter provider to wrap
     */
    private $provider;

    /**
     * @var string Filter parameters (comma-separated)
     */
    private $parameters;

    /**
     * @var string Filter name for debugging
     */
    private $filter_name;

    /**
     * @var object Utilities service for debug logging
     */
    private $utilities;

    /**
     * @var object Pipeline context with tag parameters
     */
    private $context;

    /**
     * Constructs Provider Filter wrapper.
     * 
     * @param FilterProviderInterface $provider     The provider to wrap
     * @param string                  $parameters   Filter parameters (comma-separated)
     * @param string                  $filter_name  Filter name for debugging
     * @param object                  $utilities    Utilities service
     * @param object                  $context      Pipeline context
     */
    public function __construct(
        FilterProviderInterface $provider,
        string $parameters,
        string $filter_name,
        $utilities,
        $context
    ) {
        $this->provider = $provider;
        $this->parameters = $parameters;
        $this->filter_name = $filter_name;
        $this->utilities = $utilities;
        $this->context = $context;
    }

    /**
     * Apply provider filter to image
     * 
     * Wraps the provider's apply() method to work within Imagine's
     * filter pipeline. Since both use ImageInterface, no conversion
     * is needed - just pass through with error handling.
     * 
     * Process:
     * 1. Build context with utilities and tag parameters
     * 2. Call provider's apply() method directly
     * 3. Return modified ImageInterface
     * 
     * No conversion overhead - ImageInterface passed directly!
     * 
     * @param ImageInterface $image The image to process
     * @return ImageInterface The processed image (or original on failure)
     */
    public function apply(ImageInterface $image)
    {
        try {
            // Build context for provider
            $imagine = \JCOGSDesign\JCOGSImagePro\Service\ServiceCache::get_instance(
                \Imagine\Gd\Imagine::class
            );
            
            $provider_context = [
                'imagine' => $imagine,
                'utilities' => $this->utilities,
                'tag_parameters' => $this->context->get_tag_params()
            ];

            // Call provider's apply method directly (no conversion needed!)
            $modified_image = $this->provider->apply($image, $this->parameters, $provider_context);

            // Log successful application
            $this->utilities->debug_message('filter_provider_applied', [
                'filter' => $this->filter_name,
                'provider' => $this->provider->getName(),
                'parameters' => $this->parameters
            ]);

            return $modified_image;

        } catch (\Exception $e) {
            // Log failure and return original image
            $this->utilities->debug_message('filter_provider_failed', [
                'filter' => $this->filter_name,
                'provider' => $this->provider->getName(),
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);

            // Return original image on failure (graceful degradation)
            return $image;
        }
    }

    /**
     * Get the wrapped provider instance
     * 
     * Useful for testing and debugging.
     * 
     * @return FilterProviderInterface
     */
    public function getProvider(): FilterProviderInterface
    {
        return $this->provider;
    }

    /**
     * Get filter parameters
     * 
     * @return string
     */
    public function getParameters(): string
    {
        return $this->parameters;
    }
}
